Come uscire da se un comando non è riuscito?
-
26-09-2019 - |
Domanda
Sono un noob in guscio di script. Voglio stampare un messaggio e uscire il mio script, se un comando non riesce. Ho provato:
my_command && (echo 'my_command failed; exit)
, ma non funziona. Mantiene l'esecuzione delle istruzioni seguendo questa linea nello script. Sto utilizzando Ubuntu e bash.
Soluzione
Prova:
my_command || { echo 'my_command failed' ; exit 1; }
quattro cambiamenti:
- Cambia
&&
a||
- Usa
{ }
al posto di( )
- Introdurre
;
dopoexit
e - spazi dopo
{
e prima}
Dal momento che si desidera stampare il messaggio e uscire solo quando il comando non riesce (uscite con valore diverso da zero) è necessario un ||
non un &&
.
cmd1 && cmd2
verrà eseguito cmd2
quando cmd1
riesce (uscita valore 0
). Dove, come
cmd1 || cmd2
eseguirà cmd2
quando cmd1
fallisce (valore non zero).
Utilizzando ( )
rende il comando all'interno correre in un sub-shell e chiamare un exit
da lì ti fa uscire dal sub-shell e non la shell originale, quindi l'esecuzione continua nella shell originale.
Per ovviare a questo uso { }
Le ultime due variazioni sono richiesti da bash.
Altri suggerimenti
Le altre risposte hanno coperto il diretto bene, ma si può anche essere interessati a utilizzare set -e
. Con questo, qualsiasi comando che non riesce (al di fuori di contesti specifici come test if
) farà sì che lo script di abortire. Per alcuni script, è molto utile.
Se si desidera che il comportamento per tutti i comandi nello script, basta aggiungere
set -e
set -o pipefail
all'inizio dello script. Questa coppia di opzioni dire all'interprete bash per uscire ogni volta che un comando ritorna con un-diverso da zero codice di uscita.
Questo non consente di stampare un messaggio di uscita, però.
Si noti inoltre, stato d'uscita di ogni comando viene memorizzato nella variabile di shell $ ?, quale è possibile verificare subito dopo l'esecuzione del comando. Un non-zero di stato indica il fallimento:
my_command
if [ $? -eq 0 ]
then
echo "it worked"
else
echo "it failed"
fi
Ho messo il seguente linguaggio:
echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Done."
precedere ciascun comando con un'eco informativo, e seguire ogni comando con lo stesso
Linea if [ $? -ne 0 ];...
. (Naturalmente, è possibile modificare il messaggio di errore se si desidera).
my_command
fornite si canonicamente progettato, es restituisce 0 quando riesce, quindi &&
è esattamente il contrario di ciò che si vuole. Volete ||
.
Si noti inoltre che (
non mi sembra giusto per me in bash, ma non riesco a provare da dove mi trovo. Dimmi.
my_command || {
echo 'my_command failed' ;
exit 1;
}
È anche possibile utilizzare, se si desidera mantenere lo stato di errore di uscita, e hanno un file leggibile con un solo comando per riga:
my_command1 || exit $?
my_command2 || exit $?
Questo, tuttavia, non stamperà alcun messaggio di errore aggiuntivo. Ma in alcuni casi, l'errore verrà stampato dal comando fallito in ogni caso.
Il comando incorporato shell trap
permette cattura segnali, e altre condizioni utili, tra l'esecuzione di comandi fallita (cioè, uno stato di ritorno diverso da zero). Quindi, se non si vuole esplicitamente test di stato di ritorno di ogni singolo comando si può dire trap "your shell code" ERR
e il codice shell saranno eseguiti ogni volta che un comando restituisce uno status diverso da zero. Ad esempio:
trap "echo script failed; exit 1" ERR
Si noti che come in altri casi di cattura comandi falliti, oleodotti hanno bisogno di un trattamento speciale; Quanto sopra non prenderà false | true
.
Le seguenti funzioni solo echi errori se un comando non riesce:
silently () {
label="${1}"
command="${2}"
error=$(eval "${command}" 2>&1 >"/dev/null")
if [ ${?} -ne 0 ]; then
echo "${label}: ${error}" >&2
exit 1
fi
}