Replay a Recorded Terminal Session Safely with scriptlive
You will finish with a repeatable way to replay terminal input from a script recording, using its timing log to preserve the original rhythm. Allow about fifteen minutes. You need scriptlive, a timing file, and an input log made by script. The examples use the packaged util-linux 2.39.3 command supplied by Ubuntu's bsdutils package.
The route
Jump straight to the step you need, or tick off Done means at the end.
Warning
The input log contains commands typed during the recorded session. Replaying it executes those commands in a new shell. Treat the file as executable input, not as harmless text. Do not use scriptlive with a recording you have not inspected.
1. Confirm which scriptlive you are using
Start with read-only checks. They need no elevated privileges:
$ command -v scriptlive
/usr/bin/scriptlive
$ /usr/bin/scriptlive --version
scriptlive from util-linux 2.39.3
$ dpkg-query -W -f='${Package} ${Version}\n' bsdutils
bsdutils 1:2.39.3-9ubuntu6.6
Use the absolute path when you need the packaged command. On this machine, a separate util-linux 2.42.4 executable earlier in PATH reports a different version and offers additional options. The local scriptlive(1) manpage documents 2.39.3, so this guide uses only that documented interface.
Checkpoint
If command -v does not show /usr/bin/scriptlive, either adjust PATH for this session or keep using the absolute path. Do not assume that similarly named binaries have identical options.
2. Understand the three files
A usable replay combines a timing file with an input-containing typescript. The timing file records delays between terminal updates. The input log records what was entered. The typescript is the recorded terminal stream when you use --log-io; it contains both input and output. The manpage calls these the timing output, stdin log, and combined input/output log.
For the simplest replay, use --log-timing with --log-in. The command syntax is:
$ /usr/bin/scriptlive --log-timing TIMING_FILE --log-in INPUT_FILE
Replace the capitalised names with real paths. Do not swap the files: a timing file is not a typescript, and an ordinary output-only typescript does not contain the input that scriptlive needs to drive the shell.
3. Record a small test session
If you do not already have a recording, make one with script. This changes only the files named in the command and starts an ordinary shell:
$ mkdir -p "$HOME/scriptlive-demo"
$ cd "$HOME/scriptlive-demo"
$ script --quiet --log-timing session.tm --log-in session.in session.out
Inside the recording, run a harmless command and then leave the shell:
$ printf '%s\n' 'recorded-output'
recorded-output
$ exit
The script command writes session.tm, session.in, and session.out. Check that the files exist before replaying:
$ ls -l session.tm session.in session.out
-rw-r--r-- ... session.in
-rw-r--r-- ... session.out
-rw-r--r-- ... session.tm
The exact sizes and permissions vary. If session.in is empty, you recorded no input for scriptlive to feed to the shell. If you used --log-io instead, use that combined file with --log-io during replay.
4. Inspect the input before execution
Read the input log as data before you give it to scriptlive. This is an ordinary command and does not need sudo:
$ sed -n '1,120p' session.in
Look for commands that write files, remove data, change permissions, install packages, contact remote systems, handle credentials, or restart services. Also look for shell syntax that is easy to miss in a long recording, such as command substitutions, pipes, redirects, and commands typed after a prompt changed.
Do not test an unknown recording by replaying it as root. If you need to understand it, copy it to an isolated disposable environment and inspect the copy there. There is no undo operation for arbitrary commands that the recording may run.
Checkpoint
Continue only when you recognise every command that will be sent to the shell and have a recovery plan for its state changes.
5. Replay at the recorded pace
Run the replay from the directory where you want the child shell to start:
$ /usr/bin/scriptlive --log-timing session.tm --log-in session.in
>>> scriptlive: Starting your typescript execution by /bin/bash.
printf '%s\n' 'recorded-output'
recorded-output
exit
>>> scriptlive: done.
The prompt, terminal control sequences, timing, and exact status text can differ. The useful verification is that the expected harmless output appears and the command finishes with a final done message. The new session uses your $SHELL; the manpage says it defaults to /bin/bash when that variable is not set.
Replay does not create a new typescript for you. If you need an audit trail of the replay, wrap it in a fresh script session and choose a separate output directory first. Keep the original files unchanged so you can compare the source recording with the replay.
6. Control speed and long pauses
Use --divisor when the original pace is inconvenient. A divisor greater than one speeds up the replay because it divides each recorded delay:
$ /usr/bin/scriptlive --log-timing session.tm --log-in session.in --divisor 4
The argument is a floating-point number. A value of 4 makes delays roughly one quarter as long. Keep the default when the timing itself matters, such as when reviewing an interactive failure. Use a larger divisor for a quick smoke test, but remember that very short delays can make terminal output hard to follow.
Use --maxdelay to cap a long wait:
$ /usr/bin/scriptlive --log-timing session.tm --log-in session.in --maxdelay 2
This replaces any gap longer than two seconds with a shorter wait. It changes pacing, not the input commands. Do not use it when the delay is part of the behaviour you are investigating.
7. Use a combined input/output log
If the recording was made with script --log-io, pass that file with --log-io:
$ /usr/bin/scriptlive --log-timing session.tm --log-io session.io
Use either --log-in or --log-io for the typescript argument. The timing file still comes from --log-timing (or its compatibility alias --timing). Keep the option and file pairing explicit in scripts so a future reader can see whether the source contains input only or both streams.
8. Diagnose the common failures
If the command reports a missing file, check all paths from the same working directory:
$ test -r session.tm && echo 'timing file readable'
$ test -r session.in && echo 'input file readable'
$ file session.tm session.in
A missing or malformed timing file prevents reliable pacing. An output-only typescript cannot replace an input log. If the replay starts but behaves differently, compare the shell, working directory, environment, terminal size, and available programs with the original session. Those are outside the timing file.
Do not add sudo merely because replay failed. Elevated privileges change the commands' impact and can hide the real difference between environments. Use privilege only if a specific command in the reviewed recording genuinely requires it, and then review that command again before accepting the consequences.
Done means
- You confirmed that
/usr/bin/scriptliveis the util-linux 2.39.3 command described by the local manpage. - You have a matching timing file and input-bearing typescript.
- You inspected the input before execution and did not replay an unknown file as root.
- A harmless replay produced the expected output and completed normally.
- You know when to use
--divisor,--maxdelay, and--log-io. - Any state-changing command in the recording has a documented recovery path.