Ci sono un altro paio di modi con cui puoi affrontare questo problema. Supponendo che uno dei tuoi requisiti sia eseguire uno script / funzione di shell contenente alcuni comandi di shell e controllare se lo script è stato eseguito correttamente e generare errori in caso di errori.
I comandi della shell generalmente si basano sui codici di uscita restituiti per far sapere alla shell se ha avuto successo o è fallito a causa di alcuni eventi imprevisti.
Quindi quello che vuoi fare ricade su queste due categorie
- uscire in caso di errore
- uscire e ripulire in caso di errore
A seconda di quale si desidera eseguire, sono disponibili opzioni di shell da utilizzare. Per il primo caso, la shell fornisce un'opzione con set -e
e per la seconda si potrebbe fare una trap
suEXIT
Dovrei usare exit
nel mio script / funzione?
Utilizzando exit
genere migliora la leggibilità In alcune routine, una volta che si conosce la risposta, si desidera uscire immediatamente dalla routine di chiamata. Se la routine è definita in modo tale da non richiedere ulteriori pulizie una volta rilevato un errore, non uscire immediatamente significa che devi scrivere più codice.
Quindi nei casi in cui è necessario eseguire azioni di pulizia sullo script per rendere pulita la terminazione dello script, è preferibile non utilizzare exit
.
Devo usare set -e
per errore in uscita?
No!
set -e
era un tentativo di aggiungere "rilevamento automatico degli errori" alla shell. Il suo obiettivo era far interrompere la shell ogni volta che si verificava un errore, ma presenta molte potenziali insidie, ad esempio,
I comandi che fanno parte di un if test sono immuni. Nell'esempio, se ti aspetti che si interrompa durante il test
controllo sulla directory inesistente, non lo farebbe, passa alla condizione else
set -e
f() { test -d nosuchdir && echo no dir; }
f
echo survived
I comandi in una pipeline diversa dall'ultima sono immuni. Nell'esempio seguente, poiché il codice di uscita del comando eseguito più di recente (più a destra) è considerato ( cat
) ed è stato eseguito correttamente. Questo potrebbe essere evitato impostando l' set -o pipefail
opzione, ma è ancora un avvertimento.
set -e
somecommand that fails | cat -
echo survived
Consigliato per l'uso - trap
in uscita
Il verdetto è se vuoi essere in grado di gestire un errore invece di uscire alla cieca, invece di usare set -e
, usa un trap
sullo ERR
pseudo segnale.
La ERR
trappola non consiste nell'eseguire codice quando la shell stessa esce con un codice di errore diverso da zero, ma quando qualsiasi comando eseguito da quella shell che non fa parte di una condizione (come in if cmd
, o cmd ||
) esce con uno stato di uscita diverso da zero .
La pratica generale è definire un gestore trap per fornire ulteriori informazioni di debug su quale riga e cosa causa l'uscita. Ricorda che il codice di uscita dell'ultimo comando che ha causato il ERR
segnale sarebbe ancora disponibile a questo punto.
cleanup() {
exitcode=$?
printf 'error condition hit\n' 1>&2
printf 'exit code returned: %s\n' "$exitcode"
printf 'the command executing at the time of the error was: %s\n' "$BASH_COMMAND"
printf 'command present on line: %d' "${BASH_LINENO[0]}"
# Some more clean up code can be added here before exiting
exit $exitcode
}
e usiamo questo gestore come di seguito sopra lo script che non funziona
trap cleanup ERR
Mettendo questo insieme su un semplice script che conteneva false
alla riga 15, le informazioni che avresti ottenuto come
error condition hit
exit code returned: 1
the command executing at the time of the error was: false
command present on line: 15
La trap
offre anche opzioni a prescindere l'errore basta eseguire la pulizia al termine della shell (per esempio, le vostre uscite di script di shell), il segnale EXIT
. Puoi anche eseguire il trapping su più segnali contemporaneamente. L'elenco dei segnali supportati su cui eseguire il trap può essere trovato nella trap.1p - pagina di manuale di Linux
Un'altra cosa da notare sarebbe capire che nessuno dei metodi forniti funziona se hai a che fare con sotto-shell, nel qual caso potresti dover aggiungere la tua gestione degli errori.
Su una sottostruttura con set -e
non funzionerebbe. Il false
è limitato alla sub-shell e non viene propagato a shell genitore. Per eseguire la gestione degli errori qui, aggiungi la tua logica da fare(false) || false
set -e
(false)
echo survived
Lo stesso accade trap
anche con . La logica seguente non funzionerebbe per i motivi sopra menzionati.
trap 'echo error' ERR
(false)