Enregistrement de session shell

Published: 16-08-2015

Updated: 22-05-2016

By: Maxime de Roucy

tags: script shell tmux

Pour écrire des article sur ce site j’ai souvant eu copier/coller des éléments de mon terminal. Je me suis dit qu’il serait interressant de voir s’il est possible d’enregistrer le contenu d’un terminal.

script

La command script permet de logger tous ce qui est affiché par un terminal.

Le problème c’est qu’il enregistre aussi les séquence d’échappement ANSI, xterm (ou autre)…

Il ne faut pas utiliser un program modifiant le rendu du terminal (less, more, man, interface ncurse…) lorsqu’on est dans une session loggée par script.

max@laptop % script test.log
Le script a débuté, le fichier est test.log
max@laptop % ll
total 1,8G
drwxr-xr-x 1 max users  262 30 juil. 23:11 ansible/
drwxr-xr-x 1 max users  242 11 août  14:45 Documents/
…
max@laptop % ^D
Script terminé, le fichier est test.log

Si on lit ce fichier avec less on obtient :

Le script a débuté sur dim. 16 août 2015 21:23:37 CEST
ESC[1mESC[3m%ESC[23mESC[1mESC[0m
total 1,8G
drwxr-xr-x 1 max users  262 30 juil. 23:11 ESC[0mESC[01;34mansibleESC[0m/
drwxr-xr-x 1 max users  242 11 août  14:45 ESC[01;34mDocumentsESC[0m/

Il faut le lire avec more ou less -r pour obtenir quelque chose de lisible.

Le script perl suivant permet de supprimer les séquences d’échappements.

#!/usr/bin/perl
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \r | # Remove extra carriage returns also
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
       1 while s/[^\b][\b]//g;  # remove all non-backspace followed by backspace
    print;
}

Mais avec zsh, il supprime le prompt et la commande qui a été lancée.

max@laptop % script -c 'zsh --no-rcs' test.log
Le script a débuté, le fichier est test.log
laptop% ls -l
total 1811452
drwxr-xr-x 1 max users        262 30 juil. 23:11 ansible
drwxr-xr-x 1 max users        242 11 août  14:45 Documents
…
laptop%
Script terminé, le fichier est test.log
max@laptop % ./remove-escape.pl test.log
Le script a débuté sur dim. 16 août 2015 21:39:03 CEST
max@laptop %
total 1811452
drwxr-xr-x 1 max users        262 30 juil. 23:11 ansible
drwxr-xr-x 1 max users        242 11 août  14:45 Documents
…

tmux

pipe-pane

Tmux permet de faire à la même chose que script via la commande pipe-pane.

La commande passée à pipe-pane est lancée dans un shell et son entré standard est récupère tous le contenu du « pane ». Ce contenu contient les caractères d’échappement (comme pour script). En revanche il est possible de les filtrer directement dans la commande.

max@laptop % tmux pipe-pane -o "exec sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $HOME/tmux.log"
max@laptop % ll
total 1,8G
drwxr-xr-x 1 max users  262 30 juil. 23:11 ansible/
drwxr-xr-x 1 max users  242 11 août  14:45 Documents/
…
max@laptop % tmux pipe-pane
max@laptop % less ~/tmux.log

max@laptop %
total 1,8G
drwxr-xr-x 1 max users  262 30 juil. 23:11 ansible/
drwxr-xr-x 1 max users  242 11 août  14:45 Documents/
…

Dans cette exemple j’ai fait en sorte que sed remplace sont shell de lancement (exec).

Pour désactiver le logging, il suffit de lancer la commande tmux pipe-pane sans argument. L’option -o permet de ne prendre en compte la commande que si le logging n’est pas déjà activé.

Comme vous pouvez le voir mon filtre à supprimé le prompte (j’utilise zsh). Si je ne filtre pas, il est préférable de lire le fichier avec less -r.

max@laptop % tmux pipe-pane -o "exec cat > $HOME/tmux.log"
…
max@laptop % less -r ~/tmux.log

max@laptop % ll
total 1,8G
drwxr-xr-x 1 max users  262 30 juil. 23:11 ansible/
drwxr-xr-x 1 max users  242 11 août  14:45 Documents/
…

capture-pane

capture-pane permet de faire des « capture d’écran ». Il permet de sauvegarder le contenu visible ou ce qui est dans l’historique (du pane).

max@laptop % man tmux
…	

(commande-tmux) :capture-pane ; save-buffer ~/test.log

max@laptop % cat ~/test.log
…
     capture-pane [-aepPq] [-b buffer-name] [-E end-line] [-S start-line] [-t
     target-pane]
           (alias: capturep)
     Capture the contents of a pane.  If -p is given, the output goes
     to stdout, otherwise to the buffer specified with -b or a new
     buffer if omitted.  If -a is given, the alternate screen is used,
     and the history is not accessible.  If no alternate screen
…

Cette commande à l’avantage de ne pas logger les séquence d’échappement et de pouvoir logger des commande qui modifie l’affichage du terminal. Elle ne permet pas de faire de la capture en continu.

Pour sauvegarder tous l’historique et le contenu visible :capture-pane -S - -E - ; save-buffer ~/test.log

screen

Screen permet de logger l’activité d’une session via l’option -L ou la commande log

Je n’ai jamais utiliser cette fonctionnalité.

xterm

Xterm permet de logger l’activité d’une session via l’option -l ou l’action set-logging.

Je n’ai jamais utiliser cette fonctionnalité.