web-dev-qa-db-fra.com

Comment arrêter le script bash lorsqu'une condition échoue?

Ici, il est indiqué d’utiliser les || et && sur une seule ligne pour concaténer l’exécution de commandes: Comment puis-je vérifier les erreurs apt-get dans un script bash?

J'essaie d'arrêter l'exécution d'un script si une certaine condition échoue,

par exemple.

false || echo "Obvious error because its false on left" && exit

Ici, il imprime Obvious error because its false on the left et quitte la console, ce que je voulais.

true || echo "This shouldn't print" && exit

Ici, il n’ya pas d’impression d’écho mais la commande exit est également exécutée, c’est-à-dire que la console est fermée. La commande exit ne doit-elle pas être exécutée car la commande echo de droite n’a pas été exécutée? Ou bien, par défaut, une instruction est-elle considérée comme fausse sur le côté gauche d'un opérateur &&?

Edit: J'aurais dû le mentionner auparavant, mon but était de faire écho à l'erreur et de sortir si elle n'était pas claire. w.r.t à mon cas spécifique d'erreurs de capture lorsque grouper des conditions en utilisant && et ||, la réponse @ bodhi.zazen résout le problème.

La réponse de @takatakatek explique plus clairement le contrôle de flux et les liens du guide bash sont excellents

@muru answer explique bien pourquoi ne pas utiliser set -e si vous souhaitez que des messages d'erreur personnalisés soient générés avec des alternatives utilisant Perl et trap, ce qui, à mon avis, est un moyen plus robuste et que je me vois l'utiliser dès mon deuxième script bash!

11
kosol

Vous voulez probablement (comme l'a souligné steeldriver)

true || { echo "This shouldn't print" && exit; }

Sinon, votre script lit une condition à la fois

a ou b puis quitte

Je pense que vous voulez un ou (b et sortir)?

10
Panther

Le problème est que || & && ignore uniquement une strophe ultérieure d'une chaîne de commandes lorsque la condition échoue. Si vous écrivez une structure de bloc complète, c'est parfaitement logique. Ce que tu as écrit devient ceci:

if ! true ; then
   echo "This shouldn't print"
else
   exit
fi

Ce que vous voulez c'est ceci:

if ! true ; then
   echo "This shouldn't print"
   exit
fi

Lorsque vous utilisez les opérateurs conditionnels de raccourci de Bash, il est préférable d'éviter de les mélanger. La logique est beaucoup plus facile à comprendre lorsque vous l’écrivez et vos lecteurs apprécieront votre style.

14
takatakatek

Le moyen le plus simple d'échouer en cas d'erreur est d'utiliser l'option -e de bash (set -e ou /bin/bash -e dans Shebang). Toutefois, cela ne facilite pas l'envoi de messages d'erreur personnalisés. Quelques idiomes pourraient vous simplifier la tâche:

dieà la Perl

Perl a une commande très pratique dieNAME_ qui affiche un message sur stderr et lève une exception, ce qui conduit généralement à la fin du script. Vous pouvez imiter ceci:

die () {
  ret=$?
  print "%s\n" "$@" >&2
  exit "$ret"
}

false || die "Obvious error because its false on left"
true || die "This shouldn't print"

trapERR_

La commande trap <command> peut être utilisée pour exécuter une commande lorsqu'un signal est reçu, lorsque vous quittez le script (trap ... EXIT) ou lorsqu'une commande renvoie une erreur (trap ... ERR). Donc, quelque chose comme:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR

Ensuite:

ERR_MSG="Obvious error because its false here"
false
ERR_MSG="This shouldn't print"
true

Dans les deux cas, je suggérerais d'utiliser au moins exit 1, pour indiquer que le script a échoué . Un nom exit__ plain utilisera le statut de sortie de la commande précédente, qui dans ces cas serait les commandes echoou printfname__, qui aboutiraient généralement. Enregistrer le statut de sortie de la commande en échec, comme je l’ai fait ici, serait une bonne idée.

7
muru

Vous pouvez essayer d’expérimenter un peu en lançant le script avec

#!/bin/bash -e

Le -e garantit que le script quitte le moment où quelque chose retourne faux. Un échec spécifique peut alors être évité avec something || true

5
aggregate1166877