Esci da uno script in caso di errore


141

Sto creando uno script di shell che ha una iffunzione come questa:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

Voglio che l'esecuzione dello script termini dopo aver visualizzato il messaggio di errore. Come posso farlo?

Risposte:


137

Stai cercando exit?

Questa è la migliore guida bash in giro. http://tldp.org/LDP/abs/html/

Nel contesto:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
    exit 1 # terminate and indicate error
fi

...


Quei link Bash sono FANTASTICI! Il BashFAQ sarebbe meglio posizionato come BashRecipes.
Pete Alvin,

337

Se metti set -e uno script, lo script terminerà non appena un comando al suo interno fallisce (ovvero non appena un comando restituisce uno stato diverso da zero). Questo non ti consente di scrivere il tuo messaggio, ma spesso sono sufficienti i messaggi del comando non riuscito.

Il vantaggio di questo approccio è che è automatico: non corri il rischio di dimenticare di affrontare un caso di errore.

I comandi il cui stato è testato da un condizionale (come if, &&o ||) non terminano lo script (altrimenti il ​​condizionale sarebbe inutile). Un idioma per il comando occasionale il cui fallimento non ha importanza è command-that-may-fail || true. Puoi anche set -edisattivare una parte dello script con set +e.


3
Secondo mywiki.wooledge.org/BashFAQ/105 - questa caratteristica ha una storia di oscurità e contorta nella sua determinazione di quali codici di errore dei comandi causano un'uscita automatica. Inoltre, "le regole cambiano da una versione di Bash a un'altra, poiché Bash tenta di tracciare la definizione POSIX estremamente scivolosa di questa" caratteristica "". Sono d'accordo con @Dennis Williamson e la risposta accettata di stackoverflow.com/questions/19622198/… - usa la trap "errore_handler" ERR. Anche se è una trappola!
Bondolin,

3
spesso usare la -xbandiera con la -ebandiera è abbastanza una traccia su dove il programma è all'uscita. Ciò implica che l'utente dello script è anche lo sviluppatore.
Alex,

Bello ma penso che l'OP abbia dovuto uscire dalla sceneggiatura da un'eccezione auto-definita.
vdegenne,

42

Se vuoi essere in grado di gestire un errore invece di uscire alla cieca, invece di usare set -e, usa a trapsullo ERRpseudo segnale.

#!/bin/bash
f () {
    errorCode=$? # save the exit code as the first thing done in the trap function
    echo "error $errorCode"
    echo "the command executing at the time of the error was"
    echo "$BASH_COMMAND"
    echo "on line ${BASH_LINENO[0]}"
    # do some error handling, cleanup, logging, notification
    # $BASH_COMMAND contains the command that was being executed at the time of the trap
    # ${BASH_LINENO[0]} contains the line number in the script of that command
    # exit the script or return to try again, etc.
    exit $errorCode  # or use some other value or do return instead
}
trap f ERR
# do some stuff
false # returns 1 so it triggers the trap
# maybe do some other stuff

Altre trappole possono essere impostate per gestire altri segnali, inclusi i soliti segnali Unix più gli altri segnali pseudo Bash RETURNe DEBUG.


8

Ecco il modo di farlo:

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'

Perché il messaggio FATTO a stderr?
MattBianco,

1
Questa è una pratica comune in modo da poter reindirizzare l'output dello script a stdout in modo che un altro processo possa ottenerlo senza avere i messaggi informativi nel mezzo.
supercobra,

2
Probabilmente è ugualmente pratica comune trattare qualsiasi cosa su stderr come un'indicazione di problemi.
MattBianco,

1
In passato 'set -e' ha sempre funzionato per me, ma stasera mi sono imbattuto in una situazione in un'immagine Docker di Alpine Linux in cui non ha avuto alcun effetto. Questa soluzione ha funzionato per me e mi ha riportato al lavoro. Molto apprezzato.
synthesizerpatel,

@supercobra Pratica comune? Dove?
Thorbjørn Ravn Andersen

-8

exit 1é tutto quello di cui hai bisogno. Il 1è un codice di ritorno, in modo da poter cambiare, se si vuole, ad esempio, 1a significare una corsa di successo e -1per indicare un guasto o qualcosa di simile.


13
In unix, il successo è sempre 0. Questo può aiutare quando si utilizza testo &&o ||.
mouviciel,

5
Per espandere il commento di mouviciel: negli script di shell, 0 significa sempre successo e da 1 a 255 significa fallimento. -1 è fuori portata (e spesso avrà lo stesso effetto di 255, quindi un errore come 1).
Gilles 'SO- smetti di essere malvagio' il

@mouviciel, @Gilles: grazie per le informazioni extra. È da un po 'che non mi occupo di bash.
DGH

Questo è un cattivo esempio dell'utilizzo del codice di ritorno, altrimenti sarebbe un'ottima risposta.
Brad Koch,

1
Oltre a raccomandare erroneamente 1 per il successo, -1 non è possibile (i codici di uscita non sono firmati).
Tripleee
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.