Je suis un noob en shell-scripting. Je veux imprimer un message et quitter mon script si une commande échoue. J'ai essayé:
my_command && (echo 'my_command failed; exit)
mais ça ne marche pas. Il continue d'exécuter les instructions suivant cette ligne dans le script. J'utilise Ubuntu et bash.
linux
bash
exit
exitstatus
user459246
la source
la source
Réponses:
Essayer:
Quatre changements:
&&
par||
{ }
à la place de( )
;
aprèsexit
et{
et avant}
Puisque vous souhaitez imprimer le message et quitter uniquement lorsque la commande échoue (quitte avec une valeur non nulle), vous avez besoin d'un
||
pas un&&
.s'exécutera en
cmd2
cas decmd1
succès (valeur de sortie0
). Tandis ques'exécutera en
cmd2
cas d'cmd1
échec (valeur de sortie non nulle).Utiliser
( )
rend la commande à l'intérieur d'eux exécutable dans un sous-shell et appeler un àexit
partir de là vous oblige à quitter le sous-shell et non votre shell d'origine, donc l'exécution continue dans votre shell d'origine.Pour surmonter cette utilisation
{ }
Les deux dernières modifications sont requises par bash.
la source
{ (>&2 echo 'my_command failed') ; exit 1; }
Les autres réponses ont bien couvert la question directe, mais vous pourriez également être intéressé à utiliser
set -e
. Avec cela, toute commande qui échoue (en dehors de contextes spécifiques comme lesif
tests) entraînera l'abandon du script. Pour certains scripts, c'est très utile.la source
set -e
a un ensemble de règles longues et obscures sur le moment où cela fonctionne et quand il ne fonctionne pas. (Si quelqu'un s'exécuteif yourfunction; then ...
, ilset -e
ne tirera jamais à l'intérieuryourfunction
ou quoi que ce soit qu'il appelle, car ce code est considéré comme "vérifié"). Voir la section des exercices de BashFAQ # 105 , discutant de cela et d'autres pièges (dont certains ne s'appliquent qu'à des versions de shell spécifiques, vous devez donc être sûr de tester toutes les versions qui pourraient être utilisées pour exécuter votre script).Notez également que l'état de sortie de chaque commande est stocké dans la variable shell $ ?, que vous pouvez vérifier immédiatement après l'exécution de la commande. Un état différent de zéro indique un échec:
la source
echo "Just finished step A"
, ne sachant pas que celaecho
écrasait le$?
qui allait être vérifié plus tard.Si vous voulez ce comportement pour toutes les commandes de votre script, ajoutez simplement
au début du script. Cette paire d'options indique à l'interpréteur bash de quitter chaque fois qu'une commande revient avec un code de sortie différent de zéro.
Cependant, cela ne vous permet pas d'imprimer un message de sortie.
la source
trap
commande intégrée bash.set -o pipefail
que ce n'est peut-être pas le comportement souhaité. Merci encore de l'avoir signalé!set -e
n'est pas du tout fiable, cohérent ou prévisible! Pour vous en convaincre, consultez la section des exercices du BashFAQ # 105 , ou le tableau comparant les comportements des différents obus sur in-ulm.de/~mascheck/various/set-eJ'ai piraté l'idiome suivant:
Faites précéder chaque commande d'un écho informatif et suivez chaque commande avec la même
if [ $? -ne 0 ];...
ligne. (Bien sûr, vous pouvez modifier ce message d'erreur si vous le souhaitez.)la source
if ! javac *.java; then ...
- pourquoi s'en préoccuper$?
?Fourni
my_command
est conçu de manière canonique, c'est -à- dire qu'il renvoie 0 en cas de succès, alors&&
c'est exactement le contraire de ce que vous voulez. Tu veux||
.Notez également que cela
(
ne me semble pas juste en bash, mais je ne peux pas essayer d'où je suis. Dîtes-moi.la source
Vous pouvez également utiliser, si vous souhaitez conserver l'état d'erreur de sortie, et avoir un fichier lisible avec une commande par ligne:
Cependant, cela n'imprimera aucun message d'erreur supplémentaire. Mais dans certains cas, l'erreur sera quand même imprimée par la commande ayant échoué.
la source
exit $?
;exit
utilise simplement$?
comme valeur par défaut.Le
trap
shell intégré permet d'intercepter des signaux et d'autres conditions utiles, y compris l'exécution échouée de commandes (c'est-à-dire un état de retour non nul). Donc, si vous ne voulez pas tester explicitement le statut de retour de chaque commande, vous pouvez le diretrap "your shell code" ERR
et le code shell sera exécuté à chaque fois qu'une commande retourne un statut non nul. Par exemple:trap "echo script failed; exit 1" ERR
Notez que comme pour d'autres cas de capture de commandes ayant échoué, les pipelines nécessitent un traitement spécial; ce qui précède n'attrapera pas
false | true
.la source