Imprimer et mettre à jour des lignes de log sur le terminal

Avez-vous déjà lancé une commande dans le terminal, qui prend beaucoup de temps à s’exécuter, et ne laisse qu’un curseur clignotant sur fond noir ? Comment savoir si la commande s’exécute ou si elle est bloquée ? Imprimer dans le terminal une ou plusieurs lignes de log permet de surveiller l’avancée de la commande, d’avoir une idée de la durée restante, ou de pouvoir voir s’il y a des erreurs. Cet article est un tour d’horizon sur les moyens les plus simples (et les plus puissants) à notre disposition.

Log qui se met à jour

Cet article est aussi une introduction aux codes VT100. Ce qui suit fonctionne avec tout les langages, à condition que le terminal où s’exécute la commande soit compatible VT100, ce qui est forcément le cas si vous êtes sur linux ou mac.

Méthode grossière de log dans le terminal

La première méthode à laquelle on peut penser consiste à imprimer une ligne de texte. Sans fioritures. Voilà un petit code bash d’exemple qui imprimera successivement les lignes “Tache un”, “Tache deux” et “Tache trois” en attendant une seconde entre chaque :

#!/usr/bin/bash

array=(un deux trois)

for i in ${!array[@]}; do
  echo "Tache ${array[$i]}"
  sleep 1
done

C’est brut, mais ça fonctionne. Comme on le voit dans le terminal, le log s’affiche sur trois lignes distinctes. Par contre, si le script imprime un très grand nombre de lignes, il risque de remplir le terminal qui va devenir illisible.

Effacer et réécrire la dernière ligne du terminal

Une solution plus propre consiste à écrire les lignes de log par-dessus la précédente. Voici comment procéder :

#!/usr/bin/bash

array=(un deux trois)

echo ''

for i in ${!array[@]}; do
  echo -e "\x1b[A\x1b[2KTache ${array[$i]}"
  sleep 1
done

En lançant cette commande, on voit bien les 3 lignes qui s’affichent comme précédemment, mais au lieu de créer 3 lignes distinctes sur le terminal, elles viennent se superposer pour n’afficher qu’une seule ligne.

Premièrement, il faut noter, et c’est spécifique à la commande echo, l’utilisation de l’option -e pour que echo prenne en compte les séquences commençant par un antislash. Ne nous attardons pas trop là-dessus, vous pouvez lire man echo si ça vous intéresse.

Ce type de séquence, donc la partie de texte qui commence par un antislash, est utilisé dans tous les langages de programmation. Elles permettent d’injecter des caractères spéciaux dans une chaîne de caractères. Soit parce qu’ils ne sont pas pratiques à stocker, comme par exemple la tabulation \t ou le saut de ligne \n, soit parce qu’ils n’existent pas sur le clavier.

Dans notre cas, nous utilisons deux caractères spéciaux en début de ligne : \x1b[A et \x1b[2K. On remarque qu’ils commencent tous les deux par le même code : \x1b. C’est le code de contrôle AINSI qui a pour rôle d’indiquer au terminal que ce qui suit est un code VT100. Les deux codes VT100 utilisés sont donc [A et [2K.

Si l’on regarde une référence des codes VT100 on constate que [A sert à déplacer le curseur d’une ligne vers le haut, et [2K à effacer la ligne où se trouve le curseur. Pour résumer echo -e "\x1b[A\x1b[2K" ordonne au terminal d’effacer la ligne précédente. Facile, non ?

Exercice : utiliser les codes VT100 pour imprimer du texte en gras

Essayez, pour voir si vous avez compris, d’afficher une ligne en gras en utilisant les codes VT100. La solution est ci-dessous, mais essayez par vous-même avant d’aller la voir.

echo -e "Texte normal \x1b[1mtexte en gras\x1b[m fin."

N’oubliez pas de terminer votre ligne par \1b[m, qui désactive les attributs précédemment activés, sinon tout votre terminal pourrait n’écrire qu’en gras après l’exécution de cette commande.

Newsletter

Publié par

Benj

Artisan du web à plusieurs facettes, du développement à la gestion de produits complexes en passant par le pilotage de projets internationaux.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

3 × deux =