Découverte d’un Ensemble d’Outils Magiques : Script, Scriptlive, Scriptreplay
Ce weekend, nous avons découvert un ensemble d’outils magiques, qui m’étaient jusque-là inconnu ! Un ensemble qui, à première vue, ne paie pas de mine, mais qui peut offrir beaucoup de fonctionnalités sympathiques. Ils sont au nombre de trois : script
, scriptlive
, scriptreplay
.
Contexte⌗
Je vais bientôt sortir de mission et j’ai une bonne quantité de documentation à terminer. Je pense, notamment, à la documentation de certaines procédures que j’ai faites ou refaites un nombre incalculable de fois… la documentation de POC ou autre. Ne pourrais-je pas documenter ces procédures au gré de mes explorations ?
L’idée est la suivante : j’ai une opération de mise à jour manuelle de GitLab à réaliser, par exemple. Je souhaite pouvoir lancer une session d’un terminal, au sein duquel je vais enregistrer l’ensemble des commandes tapées, mais aussi leurs résultats. Si je peux ajouter de manière astucieuse un commentaire en passant, pourquoi pas. Je pars ensuite de cet ensemble pour générer un Markdown de ce type :
Nous listons les fichiers et documents dans le répertoire courant
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
Et ainsi de suite, vous avez l’idée ? Après, je repasse dessus pour ajouter les bons commentaires ou les bonnes explications.
Should I Script or Should I Script ?⌗
Okay, go ! Que puis-je faire avec mon terminal pour rediriger stdin et stdout ?
-
Utiliser
>
pour rediriger la sortie d’une commande vers un fichier. Par exemple,ls > fichier.txt
enregistrera la sortie de la commandels
dans le fichierfichier.txt
. -
Utiliser
<
pour lire l’entrée d’une commande à partir d’un fichier. Par exemple,cat < fichier.txt
affichera le contenu du fichierfichier.txt
. -
Utiliser
>>
pour ajouter la sortie d’une commande à un fichier existant. Par exemple,echo "nouvelle ligne" >> fichier.txt
ajoutera la chaîne “nouvelle ligne” à la fin du fichierfichier.txt
. -
Utiliser
|
pour rediriger la sortie d’une commande vers une autre commande. Par exemple,ls | grep txt
affichera uniquement les fichiers dont le nom contient “txt”.
Stdout, c’est facile, stdin peut être une autre paire de manches.
Imaginons un script bash, qui démarre un bash, pour lequel je dois récupérer tout stdout et stdin.
Et là, je tombe sur cette pépite : script, ça date de 1970 quand même !!!!!
L’idée est assez simple, faisons quelques tests :
$ script test.log
Script started, output log file is 'test.log'.
$
Je reprends la main, j’ai un nouveau bash, et je peux taper les commandes que je veux :
$ echo "plop"
plop
$ ls -la
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
$ exit
Résultat, un magni… attendez… what… bougez pas, je vous montre, vous allez halluciner !
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, c’est quoi ce gibberish ?
Lors de l’utilisation de la commande script, les séquences d’échappement sont incluses. Ce sont des codes qui contrôlent l’affichage du terminal. Lorsque je déplace le curseur, que je change la couleur du texte dans mon terminal, des séquences d’échappement sont envoyées à ce dernier. Et c’est ces séquences qui rendent ce fichier illisible.
Ce fichier est appelé typescript, ce qui veut littéralement dire un script de tout ce qui est tapé, Javascript à encore frappé …
Utilisation de script⌗
Enregistrement d'une session avec horodatage :
$ script -T timing.log my_session.log
Cela commencera l’enregistrement toutes les activités du terminal dans le fichier my_session.log, ainsi que les horodatages dans le fichier timing.log.
Lecture d'une session enregistrée (les commandes ne sont pas réellement exécutées) :
$ scriptreplay timing.log my_session.log
Cela rejouera la session enregistrée dans le terminal.
Exécuter à nouveau une session enregistrée (les commandes sont réellement exécutées) :
$ scriptlive timing.log my_session.log
Différents cas d’utilisations⌗
- Demo time : Imaginez une démo infaillible ? Non, mais juste imaginez ! J’ai déjà connu le très bon demo.sh que j’ai vu en conférence. Désormais, vous réalisez votre démo une fois et vous la présentez via scriptreplay.
- Audit et log de toutes les sessions ouvertes sur un serveur.
- Documentation.
- Enseignement et formation : Enregistrez des sessions de terminal pour créer des tutoriels interactifs ou des guides étape par étape pour les étudiants ou les nouveaux employés.
- Débogage et support technique : Enregistrez des sessions problématiques pour les partager avec des équipes de support ou des collègues afin de faciliter la résolution des problèmes.
- Automatisation des tests : Utilisez les enregistrements pour tester des scripts dans différents environnements en simulant des interactions utilisateur.
Je suis ouvert à d’autres idées inspirantes sur l’utilisation de ces outils.
Conclusion⌗
Bref, dans l’histoire, j’ai ce qu’il me faut pour mon projet. Avec quelques commandes sed et tr judicieusement utilisées :
sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" test.log | tr -dc '[[:print:]]\n' > new_output
Et hop, le tour est joué. J’ai un fichier beaucoup plus exploitable. Non, je plaisante, c’est une CLI en Go ou en Python qui fera le boulot derrière.
Je vous passe toutes les galères de regex, parce que des séquences d’échappement, si on y réfléchit bien, il y en a un certain nombre :
<CTRL>-<R>
pour rechercher dans l’historique bash<CTRL>-<W>
pour supprimer le dernier mot avant le curseur<TAB>
pour la tabulation<CR>
pour le retour à la ligne (appui sur entrée)- etc.
En tout cas, pour le parsing, je m’arrêterai à 90 % et le reste fignoler à la main.
Ensuite, je souhaite approfondir mes connaissances sur les terminaux, donc attendez-vous à une suite.
Bonne nuit !