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?

  1. Use > to redirect the output of a command to a file. For example, ls > file.txt will save the output of the ls command in the file file.txt.

  2. Use < to read the input of a command from a file. For example, cat < file.txt will display the contents of the file file.txt.

  3. 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 file file.txt.

  4. 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"]
%

k/tmp/plop\]7;file://dimitriq/tmp/plop\
 dimitriq@dimitriq  /tmp/plop  [?1h=[?2004heecho "plop"echo "plop"[?1l>[?2004l

kecho\plop
%

k/tmp/plop\]7;file://dimitriq/tmp/plop\
 dimitriq@dimitriq  /tmp/plop  [?1h=[?2004hlls -lal-     l ls -lals -la[?1l>[?2004l

kls\total 0
drwxr-xr-x  2 dimitriq dimitriq   60 27 janv. 04:35 .
drwxrwxrwt 96 root     root     2500 27 janv. 04:35 ..
-rw-r--r--  1 dimitriq dimitriq    0 27 janv. 04:35 test.log
%

k/tmp/plop\]7;file://dimitriq/tmp/plop\
 dimitriq@dimitriq  /tmp/plop  [?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!