Dans un script Bash, comment puis-je quitter le script entier si une condition donnée se produit?

J’écris un script dans Bash pour tester du code. Cependant, il semble idiot de lancer les tests si la compilation du code échoue en premier lieu, auquel cas je vais simplement abandonner les tests.

Est-il possible de le faire sans envelopper le script entier dans une boucle while et en utilisant des pauses? Quelque chose comme un dun dun dun goto?

Essayez cette déclaration:

exit 1 

Remplacez 1 par les codes d’erreur appropriés. Voir aussi Codes de sortie avec des significations spéciales .

Utiliser set -e

 #!/bin/bash set -e /bin/command-that-fails /bin/command-that-fails2 

Le script se terminera après la première ligne qui échoue (renvoie un code de sortie différent de zéro). Dans ce cas, command-that-fail2 ne fonctionnera pas.

Si vous deviez vérifier le statut de retour de chaque commande, votre script ressemblerait à ceci:

 #!/bin/bash # I'm assuming you're using make cd /project-dir make if [[ $? -ne 0 ]] ; then exit 1 fi cd /project-dir2 make if [[ $? -ne 0 ]] ; then exit 1 fi 

Avec set -e, cela ressemblerait à ceci:

 #!/bin/bash set -e cd /project-dir make cd /project-dir2 make 

Toute commande qui échoue entraînera l’échec de tout le script et renverra un état de sortie que vous pouvez vérifier avec $? . Si votre script est très long ou que vous construisez beaucoup de choses, il va devenir assez moche si vous ajoutez des vérifications d’état de retour partout.

Un mec de SysOps qui m’a maltraité m’a appris la technique de la Griffe à trois doigts:

 yell() { echo "$0: $*" >&2; } die() { yell "$*"; exit 111; } try() { "$@" || die "cannot $*"; } 

Ces fonctions sont * NIX OS et shell saveur robuste. Mettez-les au début de votre script (bash ou autrement), try() votre instruction et votre code.

Explication

(basé sur le commentaire de mouton volant ).

  • yell : affiche le nom du script et tous les arguments de stderr :
    • $0 est le chemin du script;
    • $* sont tous des arguments.
    • >&2 signifie > redirect stdout vers & pipe 2 . le tuyau 1 serait lui-même stdout .
  • die fait la même chose que le yell , mais sort avec un statut de sortie non 0 , ce qui signifie «échec».
  • try utilise le || (booléen OR ), qui n’évalue que le côté droit si celui de gauche n’a pas échoué.
    • $@ est à nouveau tous les arguments, mais différents .

J’espère que ça explique tout.

Si vous appelez le script avec source , vous pouvez utiliser return sera le statut de sortie du script (utilisez une valeur différente de zéro pour l’erreur ou false). Cela fonctionnera également comme prévu, lorsque vous source le script. Si vous invoquez un script exécutable (c.-à-d. Directement avec son nom de fichier), l’instruction return produira une plainte (message d’erreur “return: ne peut que” renvoyer “à partir d’une fonction ou d’un script source”).

Si la exit est utilisée à la place de exit , lorsque le script est appelé avec source , le shell qui a démarré le script se ferme, mais un script exécutable s’exécute directement.

Pour gérer les deux cas dans le même script, vous pouvez utiliser

 return  2> /dev/null || exit  

Cela traitera n’importe quelle invocation qui pourrait convenir.

Remarque: est censé être un nombre.

J’inclus souvent une fonction appelée run () pour gérer les erreurs. Chaque appel que je veux passer est passé à cette fonction pour que le script entier se ferme en cas d’échec. L’avantage de cette solution par rapport à la solution set -e est que le script ne se ferme pas silencieusement lorsqu’une ligne échoue et peut vous indiquer le problème. Dans l’exemple suivant, la 3ème ligne n’est pas exécutée car le script se ferme à l’appel sur false.

 function run() { cmd_output=$(eval $1) return_value=$? if [ $return_value != 0 ]; then echo "Command $1 failed" exit -1 else echo "output: $cmd_output" echo "Command succeeded." fi return $return_value } run "date" run "false" run "date" 

Au lieu de if construit, vous pouvez exploiter l’ évaluation de court-circuit :

 #!/usr/bin/env bash echo $[1+1] echo $[2/0] # division by 0 but execution of script proceeds echo $[3+1] (echo $[4/0]) || exit $? # script halted with code 1 returned from `echo` echo $[5+1] 

Notez la paire de parenthèses qui est nécessaire en raison de la priorité de l’opérateur d’alternance. $? est une variable spéciale définie pour quitter le code de la dernière commande appelée.