J'observe un comportement étrange lors de l'utilisation de set -e
( errexit
), set -u
( nounset
) avec les pièges ERR et EXIT. Ils semblent liés, donc les poser dans une question semble raisonnable.
1) set -u
ne déclenche pas de pièges ERR
Code:
#!/bin/bash trap 'echo "ERR (rc: $?)"' ERR set -u echo ${UNSET_VAR}
- Attendu: le piège ERR est appelé, RC! = 0
- Réel: l'interruption ERR n'est pas appelée, RC == 1
- Remarque:
set -e
ne modifie pas le résultat
2) L'utilisation set -eu
du code de sortie dans une interruption EXIT vaut 0 au lieu de 1
Code:
#!/bin/bash trap 'echo "EXIT (rc: $?)"' EXIT set -eu echo ${UNSET_VAR}
- Attendu: le piège EXIT est appelé, RC == 1
- Réel: le trap EXIT est appelé, RC == 0
- Remarque: Lors de l'utilisation
set +e
, le RC == 1. Le piège EXIT renvoie le RC approprié lorsqu'une autre commande génère une erreur. - Edit: Il y a un article SO sur ce sujet avec un commentaire intéressant suggérant que cela pourrait être lié à la version Bash utilisée. Le test de cet extrait avec Bash 4.3.11 donne un RC = 1, donc c'est mieux. Malheureusement, la mise à niveau de Bash (à partir de 3.2.51) sur tous les hôtes n'est pas possible pour le moment, nous devons donc trouver une autre solution.
Quelqu'un peut-il expliquer l'un ou l'autre de ces comportements?
La recherche sur ces sujets n'a pas été très réussie, ce qui est plutôt surprenant compte tenu du nombre de publications sur les paramètres et les pièges de Bash. Il y a un fil de discussion , cependant, mais la conclusion est plutôt insatisfaisante.
set -e
et set -u
sont tous deux conçus spécifiquement pour tuer un shell scripté. Les utiliser dans des conditions susceptibles de déclencher leur application tuera un shell scripté. Il n'y a pas moyen de contourner cela, sauf pour ne pas les utiliser, et plutôt pour tester ces conditions lorsqu'elles s'appliquent dans une séquence de code. Donc, fondamentalement, vous pouvez écrire un bon code shell, ou vous pouvez utiliser set -eu
.
-u
ne déclencherait pas le piège ERR (c'est une erreur, alors ne devrait-il pas déclencher le piège) ou le code d'erreur est 0 au lieu de 1. Le ce dernier semble être un bug qui a déjà été corrigé dans une version ultérieure, c'est tout. Mais la première partie est assez difficile à comprendre si vous n'avez pas réalisé que les erreurs dans l'évaluation du shell (expansion des paramètres) et les erreurs réelles dans les commandes semblent être deux choses différentes. Pour la solution, eh bien, comme vous l'avez suggéré, j'essaie maintenant d'éviter -eu
et de vérifier manuellement quand c'est nécessaire.
(set -u; : $UNSET_VAR)
et similaire. Ce genre de trucs peut aussi être bon - vous pouvez en déposer beaucoup de &&
temps en temps: (set -e; mkdir dir; cd dir; touch dirfile)
si vous obtenez ma dérive. C'est juste que ce sont des contextes contrôlés - lorsque vous les définissez comme des options globales, vous perdez le contrôle et devenez contrôlé. Cependant, il existe généralement des solutions plus efficaces.
bash
rompu avec la norme et commencé à mettre des pièges en sous-coquilles. Le piège est censé être exécuté dans le même environnement d'où le retour, maisbash
il ne l'a pas fait depuis un certain temps.