J'écris un script dans Bash pour tester du code. Cependant, il semble absurde d'exécuter les tests si la compilation du code échoue en premier lieu. Dans ce cas, je vais simplement abandonner les tests.
Y a-t-il un moyen de faire cela sans insérer le script entier dans une boucle while et sans utiliser de 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 ayant une signification spéciale .
Utilisez 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 a échoué (retourne un code de sortie différent de zéro). Dans ce cas, command-that-fail2 ne s'exécutera 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 avec $? . Si votre script est très long ou que vous construisez beaucoup de choses, cela va devenir assez moche si vous ajoutez des contrôles d'état des retours partout.
Un mec SysOps insolent 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 robustes. Placez-les au début de votre script (bash ou autre), try()
votre déclaration et votre code.
(basé sur mouton volant commentaire).
yell
: affiche le nom du script et tous les arguments dans stderr
: $0
est le chemin du script;$*
sont tous des arguments. >&2
signifie que >
REDIRIGE LA SORTIE STANDARD VERS & PIPE 2
. pipe 1
serait stdout
lui-même. die
fait la même chose que yell
, mais quitte avec un état de sortie non-0, ce qui signifie «échec». try
utilise le ||
(boolean OR
), qui évalue uniquement le côté droit si le côté gauche n’a pas échoué. $@
est encore tous les arguments, mais différent . J'espère que ça explique tout.
Si vous appelez le script avec source
, vous pouvez utiliser return <x>
où <x>
sera le statut de sortie du script (utilisez une valeur différente de zéro pour error ou false). Cela fonctionnera également comme prévu lorsque vous source
le script, mais si vous appelez un script exécutable (c.-à-d. Directement avec son nom de fichier), l'instruction return renvoie une plainte (le message d'erreur "return: can only" return "d'un fonction ou script source ").
Si exit <x>
est utilisé à la place, lorsque le script est appelé avec source
, le shell qui l'a démarré est quitté, mais un script exécutable s'exécute directement correctement.
Pour traiter l'un ou l'autre cas dans le même script, vous pouvez utiliser
return <x> 2> /dev/null || exit <x>
Ceci gérera n'importe quelle invocation qui conviendra.
Note: <x>
est supposé être juste 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 afin que le script complet se ferme lorsqu'un échec survient. L'avantage de cette solution par rapport à set -e est que le script ne se ferme pas de manière silencieuse 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 lors de l'appel de 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 la construction if
, vous pouvez utiliser l'évaluation l'évaluation du 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.
J'ai la même question mais je ne peux pas la poser car ce serait un doublon.
La réponse acceptée, en utilisant exit, ne fonctionne pas lorsque le script est un peu plus compliqué. Si vous utilisez un processus en arrière-plan pour vérifier la condition, exit ferme uniquement ce processus, car il s'exécute dans un sous-shell. Pour tuer le script, vous devez explicitement le tuer (du moins, c'est le seul moyen que je connaisse).
Voici un petit script sur la façon de le faire:
#!/bin/bash
boom() {
while true; do sleep 1.2; echo boom; done
}
f() {
echo Hello
N=0
while
((N++ <10))
do
sleep 1
echo $N
# ((N > 5)) && exit 4 # does not work
((N > 5)) && { kill -9 $$; exit 5; } # works
done
}
boom &
f &
while true; do sleep 0.5; echo beep; done
C’est une meilleure réponse, mais toujours incomplète. Je ne sais vraiment pas comment me débarrasser de la boum partie.