Debug shell
| Fiche express | |
|---|---|
| Domaine | Débogage / traçage d'un script shell |
| Trace commande par commande | set -x
|
| Arrêt sur erreur | set -e
|
| Variable non définie = erreur | set -u
|
| Voir aussi | Bash · Trap |
Déboguer un script shell consiste à observer ce qu'il exécute réellement (et avec quelles valeurs de variables) sans forcément le modifier — Bash fournit plusieurs options intégrées pour ça, complétées par quelques techniques de journalisation.
Options de shell (set)
set -x # affiche chaque commande (avec les substitutions déjà faites) avant de l'exécuter
set -v # affiche chaque ligne du script telle qu'elle est lue, avant substitution
set -e # arrête le script dès qu'une commande retourne un code non nul
set -u # erreur si une variable non définie est utilisée (au lieu de la traiter comme vide)
set -o pipefail # un pipeline échoue si une seule de ses commandes échoue (pas seulement la dernière)
Ces options se combinent (set -eux) et se retirent avec un + à la place du - (set +x pour arrêter la trace). Il est courant de les activer/désactiver ponctuellement autour d'une section sensible plutôt que pour tout le script :
# section normale
set -x
# section à tracer
commande_a_verifier
set +x
# retour à la normale
Le préfixe affiché par -x peut être personnalisé via PS4 (utile pour dater chaque ligne ou afficher le numéro de ligne) :
export PS4='+ [${LINENO}] '
set -x
Capturer stdout et stderr tout en les affichant
Technique pour journaliser l'intégralité de la sortie d'un script dans un fichier sans perdre l'affichage à l'écran (utile en exécution interactive comme en cron) : rediriger le descripteur 1 vers un named pipe lu par tee, puis rediriger le descripteur 2 vers le descripteur 1.
exec > >(tee /tmp/install.log) # stdout : dupliqué vers tee (écran + fichier)
exec 2>&1 # stderr : redirigé vers le même flux que stdout
L'ordre compte : la deuxième ligne doit venir après la première pour que stderr suive stdout vers tee, sinon stderr continue de sortir directement à l'écran sans passer par le fichier.
Arrêt propre sur erreur
set -e arrête le script au premier échec, mais certains contextes le désactivent implicitement (une commande dans une condition if, un pipeline sans pipefail, une commande suivie de ||). Pour un nettoyage garanti même en cas d'arrêt brutal ou de signal, préférer un trap sur EXIT — voir Trap.