util-linux script and scriptreplay: PTY Session Logs Without False Audit Guarantees
Capture util-linux pseudo-terminal sessions, replay output with timing data, and protect input logs from passwords, control sequences, and retention mistakes.
The util-linux script command runs a shell or command through a pseudo-terminal (PTY) and records terminal data. scriptreplay can display a recorded output stream using the timing information from that session. This is useful for reproducing a terminal interaction, but the resulting files are not automatically a complete, tamper-evident audit trail: they do not prove who controlled the terminal, authenticate the host, or capture every event outside the PTY.
This guide is scoped to the util-linux implementation and its script(1) and scriptreplay(1) manuals. The current upstream release for this review is util-linux 2.42.4; distributions may package older versions or patch behavior. Check script --version and the local manual before relying on options such as multi-stream logging. The script command supplied by another operating system or package may have a different interface.
A PTY capture is different from redirecting a command
Without a terminal, many programs change behavior: they may disable interactive prompts, use different color or buffering rules, or reject input. script gives the child a terminal-like PTY, so it can record an interaction that ordinary command >output.txt 2>&1 redirection would change. The manual describes terminal data as being stored in raw form; a typescript can therefore contain carriage returns, terminal control sequences, and cursor updates rather than clean, line-oriented text.
When no command is specified, script starts the shell selected by the environment or account configuration. --command (or -c) instead starts the supplied command. Either way, the bytes in the log reflect what traversed the PTY, not a structured record of high-level actions. Use --return when the invoking shell must receive the child process’s exit status; otherwise a successful recording can mask a failed child command.
Capture output first, and treat input logging as a secret-bearing feature
For ordinary troubleshooting, start with output-only capture. The following standalone Bash example starts an interactive session in a newly created directory, then replays its output after you exit the child shell. It intentionally preserves the files for review rather than deleting evidence automatically:
#!/usr/bin/env bash
set -u
umask 077
capture_dir=$(mktemp -d) || exit 1
printf 'Capture directory: %s\n' "$capture_dir"
if script --quiet --return --log-out "$capture_dir/session.typescript" --log-timing "$capture_dir/session.timing"; then
session_status=0
else
session_status=$?
fi
scriptreplay \
--log-timing "$capture_dir/session.timing" \
--log-out "$capture_dir/session.typescript" ||
printf '%s\n' 'Replay failed; keep the original capture for inspection.' >&2
exit "$session_status"
The private directory and restrictive umask reduce access by other local users, but they do not make the data encrypted, durable, or safe from a privileged account. The default temporary location may be cleared at reboot. If the capture must be retained, move reviewed material to an approved, access-controlled evidence store and document its retention period. Do not overwrite a prior capture merely to reuse a pathname.
--log-out records terminal output. --log-in records input, while --log-io combines input and output in one file. The util-linux manual explicitly warns that input logging can capture all typed data, including passwords when terminal echo is disabled. Avoid --log-in and --log-io unless the collection is authorized, the operator has been warned, and the destination and retention controls are appropriate. A no-echo password is not excluded from an input log.
Timing files describe replay cadence, not wall-clock provenance
--log-timing writes the timing data used by scriptreplay. For output-only sessions, the classic timing format records elapsed time since the previous output and the number of bytes emitted. Input-plus-output logging uses the advanced multi-stream format by default, which tags entries such as input, output, headers, and signals. The source documents multi-stream support beginning with util-linux 2.35; older installations may not accept the same options or formats.
These deltas help reproduce the pace of terminal output; they are not a signed wall-clock timeline and should not be used alone to establish when an event occurred. If accurate time attribution matters, collect synchronized host timestamps and integrity evidence through a separate, approved logging system. script --output-limit can bound log growth and stop the child after the limit is exceeded, but the manual notes that buffering can make the final files larger than the requested size.
Replay displays data; it does not rerun the program
scriptreplay reads the saved output and timing stream and displays the recorded output again. It does not launch the commands that originally ran. Playback is best interpreted on the same kind of terminal used for capture; terminal-control bytes can render differently elsewhere. Treat a transcript from an untrusted source as terminal-control data, not as plain prose: inspect it without blindly pasting it into a shell or sending it to a sensitive terminal.
Keep the original output and timing files together. For a multi-stream capture, the timing file identifies stream records, and scriptreplay --stream out can select output rather than input. Use scriptreplay --summary to inspect an advanced timing log’s recorded session details. These tools can help a reviewer understand a session, but the files remain ordinary files that can be edited, truncated, copied, or replaced unless an external control system protects them.
Make the collection purpose explicit
Before recording, state whether the goal is troubleshooting, a reproducible demonstration, or regulated audit evidence. Those goals need different controls. A troubleshooting transcript can be redacted and kept briefly; an audit record may require authenticated operator identity, trusted time, tamper evidence, access logging, and controlled retention that script alone does not provide. Avoid recording credentials, customer data, or unrelated shell history, and review the transcript before sharing it.
Use script --help, script --version, and the local script(1) and scriptreplay(1) pages to verify the installed implementation. Confirm which streams are enabled, where the files are created, whether a command is launched inside a PTY, what exit status is preserved, and how playback treats control sequences. A terminal session log is a useful debugging artifact when its scope is explicit; it is not a substitute for an authenticated audit pipeline.
Related:
- Terminal Line Discipline and termios: Canonical Input, Signals, Echo, and Raw Mode
- PowerShell Transcription: Capture a Session Without Leaking Sensitive Output
Sources: