Replay Recorded Terminal Input with scriptlive
scriptlive takes a script recording and actually types it back into a new shell, at the original rhythm if you keep the timing file. 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, and replaying it executes those commands in a new shell. Treat the file as executable input, not harmless text. Do not run scriptlive against a recording you have not inspected.
1. Confirm which scriptlive you are using
Start with read-only checks that 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 specifically need the packaged command. On this machine, a separate util-linux 2.42.4 executable sits earlier in PATH and reports a different version with extra 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 similarly named binaries share identical options.
2. Understand the three files
A usable replay combines a timing file with an input-bearing typescript:
- The timing file records delays between terminal updates.
- The input log records what was actually typed.
- The typescript from
--log-iois the combined stream: both input and output together.
The manpage calls these the timing output, stdin log, and combined input/output log. For the simplest replay, pair --log-timing with --log-in:
$ /usr/bin/scriptlive --log-timing TIMING_FILE --log-in INPUT_FILE
Replace the capitalised names with real paths, and do not swap the files: a timing file is not a typescript, and an ordinary output-only typescript does not hold the input that scriptlive needs to drive the shell.
3. Record a small test session
No recording yet? 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 something harmless and leave the shell:
$ printf '%s\n' 'recorded-output'
recorded-output
$ exit
script writes session.tm, session.in and session.out. Check they 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
Exact sizes and permissions vary. An empty session.in means no input was recorded for scriptlive to feed the shell. If you used --log-io instead, pair that combined file with --log-io at replay time.
4. Inspect the input before execution
Read the input log as data before handing it to scriptlive. This is an ordinary command and needs no sudo:
$ sed -n '1,120p' session.in
- Look for commands that write files, remove data or change permissions.
- Look for anything that installs packages, contacts remote systems, handles credentials or restarts services.
- Look for shell syntax easy to miss in a long recording: 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 for arbitrary commands the recording might run.
Checkpoint
Continue only once you recognise every command that will be sent to the shell, and have a recovery plan for whatever state it changes.
5. Replay at the recorded pace
Run the replay from the directory where the child shell should 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, control sequences, timing and exact status text can differ. What matters is that the expected harmless output appears and the run finishes with a final done message. The new session uses your $SHELL; the manpage says it defaults to /bin/bash when that variable is unset.
Replay does not create a new typescript for you. Want an audit trail of the replay itself? Wrap it in a fresh script session pointed at a separate output directory first, and keep the originals unchanged so you can compare source and replay.
6. Control speed and long pauses
Use --divisor when the original pace is inconvenient. A divisor greater than one speeds things up, 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: 4 makes delays roughly a quarter as long. Keep the default when the timing itself matters, such as reviewing an interactive failure, and reach for a larger divisor for a quick smoke test, bearing in mind that very short delays can make terminal output hard to follow.
Use --maxdelay to cap a long wait instead:
$ /usr/bin/scriptlive --log-timing session.tm --log-in session.in --maxdelay 2
That replaces any gap longer than two seconds with a shorter one. It changes pacing, not the input commands themselves. Skip it when the delay is part of the behaviour you are investigating.
7. Use a combined input/output log
Recording made with script --log-io? Pass that file back in 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, never both. 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 at a glance whether the source holds input only, or both streams.
8. Diagnose the common failures
A missing-file report means checking every path 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 breaks reliable pacing. An output-only typescript cannot substitute for an input log. If the replay starts but behaves differently, compare shell, working directory, environment, terminal size and available programs against the original session: none of that lives in the timing file.
Do not add sudo just because a replay failed. Elevated privileges change what the commands actually do, and can hide the real difference between environments. Use privilege only when a specific, reviewed command in the recording genuinely needs it, and review that command again before accepting the consequences.
Done means
- You confirmed
/usr/bin/scriptliveis the util-linux 2.39.3 command the local manpage describes. - 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 reach for
--divisor,--maxdelayand--log-io. - Any state-changing command in the recording has a documented recovery path.