La plupart des commandes *nix utilisent la sortie d’erreur standard pour l’affichage d’informations, qu’elles soient liées à un mauvais paramètre ou à une anomalie de traitement, entre autre.
Lorsqu’on code en Bash, on écrit très souvent sur la sortie standard dite « normale », ou bien on re-dirige le flux de sortie vers un fichier de log. Lorsqu’on souhaite gérer les erreurs arrivant sur la sortie d’erreur standard, on peut choisir de les ignorer en les re-dirigeant vers /dev/null. On peut aussi choisir de rediriger ces erreurs vers le fichier de log principal, en acceptant que ces informations soient mélangées aux données du traitement. On peut également choisir de les rediriger vers un second fichier, spécialement dédié aux erreurs.
Gérer les sorties d’erreur de cette façon est tout à fait satisfaisant pour un script monolithique. Ce ne sera pas le cas si on utilise des fichiers sources partageant des fonctions communes toutes faites, dans lesquelles on peut aussi rencontrer des erreurs. C’est dans ces fonctions-là qu’il peut devenir utile de gérer plus proprement le flux de sortie en erreur.
Imaginons par exemple une fonction « factorielle » qui pourrait être utilisée un peu partout dans nos scripts. Celle-ci devra prendre obligatoirement un argument, qui plus est un nombre entier positif. Si notre argument est manquant, ou bien s’il ne correspond pas à un nombre, alors un message d’erreur sera affiché sur la sortie d’erreur standard, en plus de retourner un code d’erreur adéquat.
ARGUMENT_MANQUANT=1 PAS_UN_NOMBRE=2 function factorielle () { if test $# -eq 0 then echo "Cette fonction prend un nombre en parametre" >&2 return $ARGUMENT_MANQUANT fi if test `echo "$1" | sed s/^[0-9]*$/1/g` != "1" then echo "Le parametre [${1}] n'est pas un nombre valide" >&2 return $PAS_UN_NOMBRE fi seq -s \* $1 | bc return 0 }
Derrière chacune des deux commandes echo, c’est le >&2 (sans espace !) qui permet de rediriger le flux vers la sortie d’erreur au lieu de la sortie normale. Pour réaliser le calcul de la factorielle, une utilisation maline de seq et bc suffit. Si l’on teste notre fonction dans un terminal, on pourra alors obtenir ces différents résultats :
~$ factorielle Cette fonction prend un nombre en parametre ~$ echo $? 1 ~$ factorielle abc Le parametre [abc] n'est pas un nombre valide ~$ echo $? 2 ~$ factorielle abc 2>> /dev/null ~$ echo $? 2 ~$ factorielle 5 2>> /dev/null 120 ~$ echo $? 0