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

j'écris un script à Bash pour tester du code. Cependant, il semble stupide d'exécuter les tests si compiler le code échoue en premier lieu, auquel cas je vais juste annuler les tests.

y a-t-il un moyen pour que je puisse faire cela sans envelopper le script entier dans une boucle while et en utilisant des pauses? Quelque chose comme un dun dun dun goto?

483
demandé sur Peter Mortensen 2009-09-04 13:51:52

6 réponses

essayez cette déclaration:

exit 1

remplacer 1 par les codes d'erreur appropriés. Voir aussi codes de sortie ayant une signification spéciale .

522
répondu Michael Foukarakis 2015-08-07 07:10:15

Utiliser 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 non nul). Dans ce cas, commande-qui-fails2 ne sera pas exécuté.

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 e , il devrait ressembler à:

#!/bin/bash

set -e

cd /project-dir
make

cd /project-dir2
make

toute commande qui échoue fera échouer le script entier et retournera un statut 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 laid si vous ajoutez des contrôles de statut de retour partout.

565
répondu Shizzmo 2012-10-24 20:11:01

un type des SysOps à gros cul m'a appris une fois la technique de la griffe à trois doigts:

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

Ces fonctions sont les systèmes unix et le shell saveur robuste. Mettez - les au début de votre script (bash ou autre), try() votre déclaration et votre code.

explication

(à base de voler des moutons commentaire).

  • yell : imprimer le script nom et tous les arguments à stderr :
    • "151940920" est le chemin vers le script;
    • $* sont tous des arguments.
    • >&2 signifie > rediriger stdout vers & pipe 2 . pipe 1 serait stdout elle-même.
  • die fait la même chose que yell , mais les sorties avec un statut de sortie non 0 , qui signifie"échec".
  • try utilise le || (booléen OR ), qui évalue seulement le côté droit si le côté gauche n'a pas échoué.

l'Espérance qui explique tout.

163
répondu c.gutierrez 2017-05-23 11:47:31

si vous invoquez le script avec source , vous pouvez utiliser return <x><x> sera le statut de sortie du script (utilisez une valeur non nulle pour erreur ou false). Cela fonctionnera également comme prévu, lorsque vous source le script. Si vous invoquez un script exécutable (c'est-à-dire directement avec son nom de fichier), l'instruction return donnera lieu à une plainte (message d'erreur "return: can only `return' from a function or sourced script").

si exit <x> est utilisé à la place, lorsque le script est invoqué avec source , il aura pour résultat de quitter le shell qui a démarré le script, mais un script exécutable s'exécutera directement très bien.

pour traiter l'un ou l'autre cas dans le même script, vous pouvez utiliser

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

ceci traitera l'invocation qui peut être appropriée.

Note: <x> est supposé être juste un nombre.

15
répondu kavadias 2014-09-12 15:22:58

j'inclus souvent une fonction appelée run() pour gérer les erreurs. Chaque appel que je veux faire est passé à cette fonction de sorte que le script entier sort quand un échec est frappé. L'avantage de ceci par rapport à la solution set-e est que le script ne sort pas silencieusement quand 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 parce que le script sort à l'appel à false.

function run() {
  cmd_output=$(eval )
  return_value=$?
  if [ $return_value != 0 ]; then
    echo "Command  failed"
    exit -1
  else
    echo "output: $cmd_output"
    echo "Command succeeded."
  fi
  return $return_value
}
run "date"
run "false"
run "date"
9
répondu velotron 2013-09-18 19:21:51

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]

noter 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 le code de sortie de la commande la plus récente appelée.

5
répondu skalee 2013-09-04 12:35:39