J'ai un script Bash Shell qui appelle un certain nombre de commandes. J'aimerais que le script shell se ferme automatiquement avec une valeur de retour de 1 si l'une des commandes renvoie une valeur non nulle.
Est-ce possible sans vérifier explicitement le résultat de chaque commande?
par exemple.
dosomething1
if [[ $? -ne 0 ]]; then
exit 1
fi
dosomething2
if [[ $? -ne 0 ]]; then
exit 1
fi
Ajoutez ceci au début du script:
set -e
Cela entraînera la fermeture immédiate du shell si une commande simple se ferme avec une valeur de sortie différente de zéro. Une commande simple est une commande ne faisant pas partie d'un if, While, ou tant que test, ou d'une partie d'un && ou || liste.
Reportez-vous à la page de manuel bash (1) de la commande interne "set" pour plus de détails.
Personnellement, je lance presque tous les scripts Shell avec "set -e". C'est vraiment énervant de continuer obstinément un script quand quelque chose échoue au milieu et rompt les hypothèses pour le reste du script.
Pour ajouter à la réponse acceptée:
Gardez à l'esprit que set -e
n'est parfois pas assez, surtout si vous avez des pipes.
Par exemple, supposons que vous ayez ce script
#!/bin/bash
set -e
./configure > configure.log
make
... qui fonctionne comme prévu: une erreur dans configure
interrompt l'exécution.
Demain, vous apportez un changement apparemment trivial:
#!/bin/bash
set -e
./configure | tee configure.log
make
... et maintenant ça ne marche pas. Ceci est expliqué ici , et une solution de contournement (Bash uniquement) est fournie:
#!/bin/bash régler -e set -o pipefail ./ configure | tee configure.log make
Les déclarations if dans votre exemple sont inutiles. Fais-le comme ça:
dosomething1 || exit 1
Si vous suivez les conseils de Ville Laurikari et utilisez set -e
, vous devrez peut-être utiliser certaines commandes:
dosomething || true
Le || true
donnera au pipeline de commandes une valeur de retour true
même si la commande échoue pour que l'option -e
ne tue pas le script.
Si vous avez un nettoyage à faire à la sortie, vous pouvez également utiliser 'trap' avec le pseudo-signal ERR. Cela fonctionne de la même manière que l’interception de INT ou de tout autre signal; bash renvoie ERR si une commande se termine avec une valeur différente de zéro:
# Create the trap with
# trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah
Ou, surtout si vous utilisez "set -e", vous pouvez capturer EXIT; votre interruption sera alors exécutée lorsque le script se terminera pour une raison quelconque, y compris une fin normale, des interruptions, une sortie provoquée par l'option -e, etc.
Exécutez-le avec -e
ou set -e
en haut.
Regardez aussi set -u
.
La variable $?
est rarement nécessaire. Le pseudo-idiome command; if [ $? -eq 0 ]; then X; fi
devrait toujours être écrit sous la forme if command; then X; fi
.
Le cas où $?
est requis est le cas où il doit être comparé à plusieurs valeurs:
command
case $? in
(0) X;;
(1) Y;;
(2) Z;;
esac
ou lorsque $?
doit être réutilisé ou autrement manipulé:
if command; then
echo "command successful" >&2
else
ret=$?
echo "command failed with exit code $ret" >&2
exit $ret
fi
#!/bin/bash -e
devrait suffire.
Une expression comme
dosomething1 && dosomething2 && dosomething3
arrêtera le traitement lorsque l’une des commandes retournera avec une valeur différente de zéro. Par exemple, la commande suivante n'imprimera jamais "terminé":
cat nosuchfile && echo "done"
echo $?
1