C'est une vieille question, mais aucune des réponses ici ne traite de l'utilisation de set -e
aka set -o errexit
dans les scripts de gestion des paquets Debian. L'utilisation de cette option est obligatoire dans ces scripts, selon la politique Debian; l'intention est apparemment d'éviter toute possibilité de condition d'erreur non gérée.
En pratique, cela signifie que vous devez comprendre dans quelles conditions les commandes que vous exécutez peuvent renvoyer une erreur et gérer chacune de ces erreurs de manière explicite.
Les pièges courants sont par exemple diff
(retourne une erreur quand il y a une différence) et grep
(retourne une erreur quand il n'y a pas de correspondance). Vous pouvez éviter les erreurs avec une gestion explicite:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2
(Remarquez également comment nous prenons soin d'inclure le nom du script actuel dans le message et d'écrire des messages de diagnostic sur l'erreur standard au lieu de la sortie standard.)
Si aucune manipulation explicite n'est vraiment nécessaire ou utile, ne faites rien explicitement:
diff this that || true
grep cat food || :
(L'utilisation de la :
commande no-op du shell est légèrement obscure, mais assez courante.)
Juste pour réitérer,
something || other
est un raccourci pour
if something; then
: nothing
else
other
fi
c'est-à-dire que nous disons explicitement other
devrait être exécuté si et seulement si something
échoue. Le longhand if
(et d'autres instructions de contrôle de flux shell comme while
, until
) est également un moyen valide de gérer une erreur (en effet, si ce n'était pas le cas, les scripts shell avec set -e
ne pourraient jamais contenir d'instructions de contrôle de flux!)
Et aussi, juste pour être explicite, en l'absence d'un gestionnaire comme celui-ci, set -e
le script entier échouerait immédiatement avec une erreur s'il diff
trouvait une différence ou s'il grep
ne trouvait pas de correspondance.
D'un autre côté, certaines commandes ne produisent pas d'état de sortie d'erreur lorsque vous le souhaitez. Les commandes généralement problématiques sont find
(l'état de sortie ne reflète pas si les fichiers ont été réellement trouvés) et sed
(l'état de sortie ne révélera pas si le script a reçu une entrée ou s'il a effectivement exécuté des commandes avec succès). Un simple garde dans certains scénarios consiste à diriger vers une commande qui crie s'il n'y a pas de sortie:
find things | grep .
sed -e 's/o/me/' stuff | grep ^
Il convient de noter que l'état de sortie d'un pipeline est l'état de sortie de la dernière commande de ce pipeline. Les commandes ci-dessus masquent donc complètement l'état de find
et sed
, et vous indiquent uniquement si vous avez grep
finalement réussi.
(Bash, bien sûr, set -o pipefail
mais les scripts de paquets Debian ne peuvent pas utiliser les fonctionnalités de Bash. La politique dicte fermement l'utilisation de POSIX sh
pour ces scripts, bien que ce ne soit pas toujours le cas.)
Dans de nombreuses situations, c'est quelque chose à surveiller séparément lors du codage défensif. Parfois, vous devez par exemple parcourir un fichier temporaire pour voir si la commande qui a produit cette sortie s'est terminée avec succès, même si l'idiome et la commodité vous inciteraient autrement à utiliser un pipeline shell.