C'est une vieille question, mais aucune des réponses ici ne traite de l'utilisation de set -eaka set -o errexitdans 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 otherdevrait ê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 -ene 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 -ele script entier échouerait immédiatement avec une erreur s'il difftrouvait une différence ou s'il grepne 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 findet sed, et vous indiquent uniquement si vous avez grepfinalement réussi.
(Bash, bien sûr, set -o pipefailmais les scripts de paquets Debian ne peuvent pas utiliser les fonctionnalités de Bash. La politique dicte fermement l'utilisation de POSIX shpour 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.