Questa è una vecchia domanda, ma nessuna delle risposte qui parla dell'uso di set -eaka set -o errexitnegli script di gestione dei pacchetti Debian. L'uso di questa opzione è obbligatorio in questi script, secondo la politica Debian; l'intento è apparentemente quello di evitare qualsiasi possibilità di una condizione di errore non gestita.
Ciò significa in pratica che devi capire in quali condizioni i comandi che esegui potrebbero restituire un errore e gestirli in modo esplicito.
I gotcha comuni sono ad es. diff(Restituisce un errore in caso di differenza) e grep(restituisce un errore in assenza di corrispondenza). È possibile evitare gli errori con la gestione esplicita:
diff this that ||
echo "$0: there was a difference" >&2
grep cat food ||
echo "$0: no cat in the food" >&2
(Notare anche come ci prendiamo cura di includere il nome dello script corrente nel messaggio e scrivere messaggi diagnostici in errore standard invece che in output standard.)
Se nessuna gestione esplicita è davvero necessaria o utile, non fare esplicitamente nulla:
diff this that || true
grep cat food || :
(L'uso del :comando no-op della shell è leggermente oscuro, ma abbastanza comune.)
Solo per ribadire,
something || other
è una scorciatoia per
if something; then
: nothing
else
other
fi
cioè diciamo esplicitamente che otherdovrebbe essere eseguito se e solo se somethingfallisce. Il longhand if(e altre dichiarazioni di controllo del flusso della shell comewhile , until) è anche un modo valido per gestire un errore (in effetti, se non lo fosse, gli script di shell con set -enon potrebbero mai contenere istruzioni di controllo del flusso!)
Inoltre, solo per essere espliciti, in assenza di un gestore come questo, set -efarebbe fallire immediatamente l'intero script con un errore sediff trovasse una differenza o se grepnon trovasse una corrispondenza.
D'altra parte, alcuni comandi non producono uno stato di uscita dell'errore quando lo si desidera. Comuni comunemente problematici sono find(lo stato di uscita non riflette se i file sono stati effettivamente trovati) e sed(lo stato di uscita non rivelerà se lo script ha ricevuto input o effettivamente eseguito correttamente i comandi). Una semplice protezione in alcuni scenari è convogliare un comando che urla se non c'è output:
find things | grep .
sed -e 's/o/me/' stuff | grep ^
Va notato che lo stato di uscita di una pipeline è lo stato di uscita dell'ultimo comando in quella pipeline. Quindi i comandi precedenti in realtà mascherano completamente lo stato di finde sed, e ti dicono solo se alla grepfine ci sono riusciti.
(Bash, ovviamente, l'ha fatto set -o pipefail ; ma gli script di pacchetti Debian non possono usare le funzionalità di Bash. La politica impone fermamente l'uso di POSIX shper questi script, anche se non è sempre stato così).
In molte situazioni, questo è qualcosa a cui prestare attenzione separatamente quando si codifica in modo difensivo. A volte è necessario, ad esempio, passare attraverso un file temporaneo in modo da poter vedere se il comando che ha prodotto quell'output è terminato correttamente, anche quando il linguaggio e la convenienza ti indirizzerebbero altrimenti a utilizzare una pipeline di shell.