linux vecchi Annullare uno script di shell se qualche comando restituisce un valore diverso da zero?




variabili bash (8)

Ho uno script di shell Bash che richiama un numero di comandi. Mi piacerebbe che lo script della shell uscisse automaticamente con un valore di ritorno di 1 se uno qualsiasi dei comandi restituisce un valore diverso da zero.

Questo è possibile senza controllare esplicitamente il risultato di ogni comando?

per esempio

dosomething1
if [[ $? -ne 0 ]]; then
    exit 1
fi

dosomething2
if [[ $? -ne 0 ]]; then
    exit 1
fi

Aggiungi questo all'inizio dello script:

set -e

Ciò causerà l'uscita immediata della shell se un comando semplice termina con un valore di uscita diverso da zero. Un semplice comando è un comando che non fa parte di un comando if, while o until, o parte di un && or || elenco.

Vedi la pagina man di bash (1) sul comando interno "set" per maggiori dettagli.

Io personalmente avvio quasi tutti gli script di shell con "set -e". È davvero fastidioso che una sceneggiatura continui ostinatamente quando qualcosa non va nel mezzo e rompe le ipotesi per il resto della sceneggiatura.


ne aggiungo un'altra per riferimento dato che c'era una domanda aggiuntiva per l'input di Mark Edgars e qui c'è un altro esempio e tocca l'argomento in generale:

[[ `cmd` ]] && echo success_else_silence

che è lo stesso di cmd || exit errcode cmd || exit errcode come qualcuno ha mostrato.

per esempio. Voglio assicurarmi che una partizione sia smontata se montata:

[[ `mount | grep /dev/sda1` ]] && umount /dev/sda1 

Per aggiungere alla risposta accettata:

Ricorda che set -e volte non è sufficiente, specialmente se hai pipe.

Ad esempio, supponiamo di avere questo script

#!/bin/bash
set -e 
./configure  > configure.log
make

... che funziona come previsto: un errore in configure interrompe l'esecuzione.

Domani compierai un cambiamento apparentemente banale:

#!/bin/bash
set -e 
./configure  | tee configure.log
make

... e ora non funziona. Questo è spiegato here e viene fornita una soluzione alternativa (solo Bash):

#!/bin/bash
set -e 
set -o pipefail

./configure  | tee configure.log
make

Eseguilo con -e o set -e in alto.

Guarda anche set -u .


Se hai bisogno di eseguire la pulizia all'uscita, puoi anche usare 'trap' con l'ERR dello pseudo-segnale. Funziona allo stesso modo di intrappolare INT o qualsiasi altro segnale; bash lancia ERR se qualsiasi comando termina con un valore diverso da zero:

# Create the trap with   
#    trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah

O, soprattutto se stai usando "set -e", potresti intrappolare EXIT; la tua trappola verrà quindi eseguita quando lo script viene chiuso per qualsiasi motivo, inclusa una fine normale, interruzioni, un'uscita causata dall'opzione -e, ecc.


Le istruzioni if ​​nel tuo esempio non sono necessarie. Fallo in questo modo:

dosomething1 || exit 1

Se segui i consigli di Ville Laurikari e usi set -e allora per alcuni comandi potresti aver bisogno di usare questo:

dosomething || true

|| true || true renderà il command pipe un true valore di ritorno anche se il comando fallisce, quindi l'opzione -e non ucciderà lo script.


Un'espressione come

dosomething1 && dosomething2 && dosomething3

interromperà l'elaborazione quando uno dei comandi ritorna con un valore diverso da zero. Ad esempio, il seguente comando non stamperà mai "done":

cat nosuchfile && echo "done"
echo $?
1

#!/bin/bash -e

dovrebbe essere sufficiente







shell