Il y a beaucoup de points de sortie dans mon code bash. J'ai besoin de faire un travail de nettoyage à la sortie, j'ai donc utilisé trap pour ajouter un rappel pour la sortie comme ceci:
trap "mycleanup" EXIT
Le problème est qu'il existe différents codes de sortie, j'ai besoin de faire des travaux de nettoyage correspondants. Puis-je obtenir le code de sortie dans mycleanup?
Je pense que vous pouvez utiliser $?
pour obtenir le code de sortie.
La réponse acceptée est fondamentalement correcte, je veux juste clarifier les choses.
L'exemple suivant fonctionne bien:
#!/bin/bash
cleanup() {
rv=$?
rm -rf "$tmpdir"
exit $rv
}
tmpdir="$(mktemp)"
trap "cleanup" INT TERM EXIT
# Do things...
Mais vous devez être plus prudent si vous effectuez un nettoyage en ligne, sans fonction. Par exemple, cela ne fonctionnera pas:
trap "rv=$?; rm -rf $tmpdir; exit $rv" INT TERM EXIT
Au lieu de cela, vous devez échapper au $rv
et $?
variables:
trap "rv=\$?; rm -rf $tmpdir; exit \$rv" INT TERM EXIT
Vous pourriez également vouloir vous échapper $tmpdir
, car il sera évalué lorsque la ligne d'interruption sera exécutée et si la valeur tmpdir
change plus tard, cela ne vous donnera pas le comportement attendu.
Edit: Utilisez shellcheck pour vérifier vos scripts bash et être conscient de problèmes comme celui-ci.
J'ai trouvé qu'il était préférable de séparer le piège EXIT du piège pour les autres signaux
Exemple de script de test d'interruption ...
umask 77
tmpfile=`tmpfile.$$`
trap 'rm -f "$tmpfile"' EXIT
trap 'exit 2' HUP INT QUIT TERM
touch $tmpfile
read -r input
exit 10
Le fichier temporaire est nettoyé. La valeur de sortie de fichier de 10 est préservée! Les interruptions entraînent une valeur de sortie de 2
Fondamentalement, tant que vous n'utilisez pas "exit" dans un piège EXIT, il sortira avec la valeur de sortie d'origine préservée.
À CÔTÉ: Notez la citation dans le piège EXIT. Cela me permet de modifier le fichier à nettoyer pendant la durée de vie des scripts. J'inclus souvent un test pour l'existence du fichier $ tmp avant d'essayer de le supprimer, donc je n'ai même pas besoin de le définir au début du script, seulement avant de le créer.