Discovery of a Magical Toolkit: Script, Scriptlive, Scriptreplay
This weekend, we discovered a magical set of tools, which were unknown to me until now! A set that, at first glance, does not look very impressive, but can offer a lot of nice functionalities. There are three of them: script
, scriptlive
, scriptreplay
.
Background⌗
I will soon be leaving my mission and I have a good amount of documentation to finish. I am thinking, in particular, of documenting some procedures that I have done or redone countless times… documentation of POCs or others. Could I not document these procedures in the course of my explorations?
The idea is as follows: I have a manual GitLab update operation to perform, for example. I want to be able to launch a terminal session, within which I will record all the commands typed, but also their results. If I can cleverly add a comment along the way, why not. I then start from this set to generate a Markdown of this type:
We list the files and documents in the current directory
ls -la
Voici la sortie de la commande :
total 44 drwxr-xr-x 2 dimitriq dimitriq 260 27 janv. 00:48 . drwxrwxrwt 95 root root 2480 27 janv. 03:27 .. -rw-r--r-- 1 dimitriq dimitriq 197 27 janv. 00:18 in -rw-r--r-- 1 dimitriq dimitriq 1951 27 janv. 00:05 parse_and_generate.go -rw-r--r-- 1 dimitriq dimitriq 1087 27 janv. 00:50 sheh.txt -rw-r--r-- 1 dimitriq dimitriq 154 27 janv. 00:04 template.md -rw-r--r-- 1 dimitriq dimitriq 1110 27 janv. 00:48 test.log -rw-r--r-- 1 dimitriq dimitriq 247 27 janv. 00:48 time.txt
And so on, you get the idea? Afterward, I go over it again to add the right comments or the right explanations.
Should I Script or Should I Script ?⌗
Okay, go! What can I do with my terminal to redirect stdin and stdout?
-
Use
>
to redirect the output of a command to a file. For example,ls > file.txt
will save the output of thels
command in the filefile.txt
. -
Use
<
to read the input of a command from a file. For example,cat < file.txt
will display the contents of the filefile.txt
. -
Use
>>
to append the output of a command to an existing file. For example,echo "new line" >> file.txt
will add the string “new line” to the end of the filefile.txt
. -
Use
|
to redirect the output of one command to another command. For example,ls | grep txt
will display only the files whose name contains “txt”.
Stdout, that’s easy, stdin might be another story.
Imagine a bash script, which starts a bash, for which I need to retrieve all stdout and stdin.
And there, I come across this gem: script, it dates back to 1970 no less!!!!!
The idea is quite simple, let’s do some tests:
$ script test.log
Script started, output log file is 'test.log'.
$
I take control, I have a new bash, and I can type whatever commands I want:
$ echo "plop"
plop
$ ls -la
total 0
drwxr-xr-x 2 dimitriq dimitriq 60 Jan 27 04:35 .
drwxrwxrwt 96 root root 2500 Jan 27 04:35 ..
-rw-r--r-- 1 dimitriq dimitriq 0 Jan 27 04:35 test.log
$ exit
Result, a magni… wait… what… hold on, I’ll show you, you’re going to freak out!
Script started on 2024-01-27 04:35:13+01:00 [TERM="screen-256color" TTY="/dev/pts/2" COLUMNS="173" LINES="21"]
[1m[3m%[23m[1m[0m
k/tmp/plop\]7;file://dimitriq/tmp/plop\
[0m[23m[24m[J[39m[0m[49m[40m[39m dimitriq@dimitriq [44m[30m[30m /tmp/plop [49m[34m[39m [K[?1h=[?2004hee[90mcho "plop"[39m[10De[39mc[39mh[39mo[39m [39m"[39mp[39ml[39mo[39mp[39m"[?1l>[?2004l
kecho\plop
[1m[3m%[23m[1m[0m
k/tmp/plop\]7;file://dimitriq/tmp/plop\
[0m[23m[24m[J[39m[0m[49m[40m[39m dimitriq@dimitriq [44m[30m[30m /tmp/plop [49m[34m[39m [K[?1h=[?2004hll[90ms -la[39ml[39m-[39m [39m [39m [39m l l[90ms -la[39ml[39ms[39m [39m-[39ml[39ma[?1l>[?2004l
kls\total 0
drwxr-xr-x 2 dimitriq dimitriq 60 27 janv. 04:35 [0m[34m.[0m
drwxrwxrwt 96 root root 2500 27 janv. 04:35 [30;42m..[0m
-rw-r--r-- 1 dimitriq dimitriq 0 27 janv. 04:35 [01;32mtest.log[0m
[1m[3m%[23m[1m[0m
k/tmp/plop\]7;file://dimitriq/tmp/plop\
[0m[23m[24m[J[39m[0m[49m[40m[39m dimitriq@dimitriq [44m[30m[30m /tmp/plop [49m[34m[39m [K[?1h=[?2004h[?2004l
Script done on 2024-01-27 04:35:49+01:00 [COMMAND_EXIT_CODE="0"]
What the hell, what’s this gibberish?
When using the script command, escape sequences are included. These are codes that control the display of the terminal. When I move the cursor, change the text color in my terminal, escape sequences are sent to it. And it’s these sequences that make this file unreadable.
This file is called a typescript, which literally means a script of everything that is typed, JavaScript has struck again …
Using script⌗
Recording a session with timestamping:
$ script -T timing.log my_session.log
This will start recording all terminal activities in the file my_session.log, as well as timestamps in the file timing.log.
Playing back a recorded session (commands are not actually executed):
$ scriptreplay timing.log my_session.log
This will replay the recorded session in the terminal.
Re-executing a recorded session (commands are actually executed):
$ scriptlive timing.log my_session.log
Different Use Cases⌗
- Demo time: Imagine a foolproof demo? No, but just imagine! I have already known the very good demo.sh that I saw at conferences. Now, you do your demo once and present it via scriptreplay.
- Audit and log of all sessions opened on a server.
- Documentation.
- Teaching and training: Record terminal sessions to create interactive tutorials or step-by-step guides for students or new employees.
- Debugging and technical support: Record problematic sessions to share with support teams or colleagues to facilitate problem-solving.
- Test automation: Use recordings to test scripts in different environments by simulating user interactions.
I am open to other inspiring ideas on the use of these tools.
Conclusion⌗
In short, in the story, I have what I need for my project. With some judiciously used sed and tr commands:
sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" test.log | tr -dc '[[:print:]]\n' > new_output
And voila, job done. I have a much more usable file. No, I’m kidding, it’s a CLI in Go or Python that will do the work behind.
I’ll skip all the regex hassles because if you think about it, there are a number of escape sequences:
<CTRL><R>
to search in bash history<CTRL><W>
to delete the last word before the cursor<TAB>
for tabulation<CR>
for newline (pressing enter)- etc.
In any case, for parsing, I’ll stop at 90% and the rest tweak by hand.
Next, I want to deepen my knowledge of terminals, so expect a sequel.
Good night!