Question Dans un script Bash, comment puis-je quitter le script entier si une certaine condition se produit?


J'écris un script dans Bash pour tester du code. Cependant, il semble stupide d'exécuter les tests si la compilation du code échoue en premier lieu, auquel cas j'arrêterai 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 aller à?


457
2017-09-04 09:51


origine


Réponses:


Essayez cette déclaration:

exit 1

Remplacer 1 avec des codes d'erreur appropriés. Voir également Codes de sortie avec des significations spéciales.


494
2017-09-04 09:53



Utilisation 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, commande-qui-échoue2 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 à:

#!/bin/bash

set -e

cd /project-dir
make

cd /project-dir2
make

Toute commande qui échoue entraîne l'échec du script entier et renvoie un statut de sortie que vous pouvez vérifier $?. Si votre script est très long ou que vous construisez beaucoup de choses, il deviendra très moche si vous ajoutez des contrôles de statut de retour partout.


545
2017-09-04 15:18



Un mec SysOps méchant m'a une fois 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 autre), try() votre déclaration et code sur.

Explication

(basé sur moutons volants commentaire).

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

J'espère que cela explique tout.


150
2017-08-26 21:24



Si vous invoquez le script avec source, vous pouvez utiliser return <x> où <x> sera l'état de sortie du script (utilisez une valeur non nulle pour error ou false). Cela fonctionnera aussi comme prévu, quand vous source le script. Si vous invoquez un script exécutable (c'est-à-dire directement avec son nom de fichier), l'instruction return entraînera un message d'erreur (message d'erreur "return: peut uniquement renvoyer" d'une fonction ou d'un script source ").

Si exit <x> est utilisé à la place, lorsque le script est appelé avec source, cela se traduira par la sortie du shell qui a lancé le script, mais un script exécutable s'exécutera directement.

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

return <x> 2> /dev/null || exit <x>

Cela traitera n'importe quelle invocation qui pourrait convenir.

Remarque: <x> est censé être juste un nombre.


11
2017-09-12 14:56



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 version -e définie est que le script ne se termine pas silencieusement lorsqu'une ligne échoue et peut vous dire quel est 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"

9
2017-09-18 19:21



Au lieu de if construire, vous pouvez tirer parti de la é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.


4
2017-09-02 16:52