Cosa significa set -e in uno script bash?

Sto studiando il contenuto di questo file preinst che lo script esegue prima che il pacchetto venga decompresso dal suo file Debian archive (.deb).

Lo script ha il seguente codice:

#!/bin/bash set -e # Automatically added by dh_installinit if [ "$1" = install ]; then if [ -d /usr/share/MyApplicationName ]; then echo "MyApplicationName is just installed" return 1 fi rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf rm -Rf $HOME/.local/share/file-manager/actions/* fi # End automatically added section 

La mia prima domanda riguarda la linea:

 set -e 

Penso che il resto dello script sia piuttosto semplice: controlla se il gestore di pacchetti Debian / Ubuntu sta eseguendo un’operazione di installazione. Se lo è, controlla se la mia applicazione è stata appena installata sul sistema. Se lo ha, lo script stampa il messaggio “MyApplicationName è appena installato” e termina ( return 1 significa che termina con un “errore”, vero?).

Se l’utente sta chiedendo al sistema di pacchetti Debian / Ubuntu di installare il mio pacchetto, lo script cancella anche due directory.

È giusto o mi manca qualcosa?

Dal help set :

  -e Exit immediately if a command exits with a non-zero status. 

Ma è considerato come una ctriggers pratica da alcune persone (bash FAQ e simili come persone che scrivono queste FAQ su irc freenode #bash), meglio usare:

 trap 'do_something' ERR 

per eseguire la funzione do_something quando si verificheranno degli errori.

Vedi http://mywiki.wooledge.org/BashFAQ/105

set -e ferma l’esecuzione di uno script se un comando o una pipeline ha un errore – che è l’opposto del comportamento di shell predefinito, che è quello di ignorare gli errori negli script. Digitare la guida help set in un terminale per vedere la documentazione di questo comando integrato.

Come per bash – Il manuale Set Builtin , se -e / errexit è impostato, la shell si chiude immediatamente se una pipeline consiste in un singolo comando semplice , una lista o un comando composto restituisce uno stato diverso da zero.

Per impostazione predefinita, lo stato di uscita di una pipeline è lo stato di uscita dell’ultimo comando nella pipeline, a meno che l’opzione pipefail sia abilitata (è disabilitata per impostazione predefinita).

In tal caso, lo stato di restituzione della pipeline dell’ultimo comando (più a destra) per uscire con uno stato diverso da zero o zero se tutti i comandi vengono eseguiti correttamente.

Se desideri eseguire qualcosa in uscita, prova a definire il trap , ad esempio:

 trap onexit EXIT 

dove onexit è la tua funzione per fare qualcosa in uscita, come sotto che sta stampando la traccia dello stack semplice:

 onexit(){ while caller $((n++)); do :; done; } 

Esiste un’opzione simile -E / errtrace che verrebbe intrappolata su ERR, ad esempio:

 trap onerr ERR 

Esempi

Esempio di stato zero:

 $ true; echo $? 0 

Esempio di stato diverso da zero:

 $ false; echo $? 1 

Esempi di stato di negazione:

 $ ! false; echo $? 0 $ false || true; echo $? 0 

Prova con pipefail disabilitato:

 $ bash -c 'set +o pipefail -e; true | true | true; echo success'; echo $? success 0 $ bash -c 'set +o pipefail -e; false | false | true; echo success'; echo $? success 0 $ bash -c 'set +o pipefail -e; true | true | false; echo success'; echo $? 1 

Prova con pipefail abilitato:

 $ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $? 1 

Ho trovato questa domanda mentre cercavo su Google, cercando di capire quale fosse lo stato di uscita per uno script che è stato interrotto a causa di un set -e . La risposta non mi è sembrata ovvia; quindi questa risposta. Fondamentalmente, set -e interrompe l’esecuzione di un comando (ad esempio uno script di shell) e restituisce il codice di stato di uscita del comando che ha avuto esito negativo (cioè lo script interno, non lo script esterno) .

Ad esempio, supponiamo di avere uno script di shell outer-test.sh :

 #!/bin/sh set -e ./inner-test.sh exit 62; 

Il codice per inner-test.sh è:

 #!/bin/sh exit 26; 

Quando outer-script.sh dalla riga di comando, il mio script esterno termina con il codice di uscita dello script interno:

 $ ./outer-test.sh $ echo $? 26