Come posso scrivere uno script di shell che esce, se una parte di esso fallisce? Ad esempio, se il seguente snippet di codice non riesce, lo script dovrebbe terminare.
n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3
Answer
Un approccio potrebbe essere quello di aggiungere set -e
allinizio dello script. Ciò significa (da help set
):
-e Exit immediately if a command exits with a non-zero status.
Quindi se uno qualsiasi dei tuoi comandi fallisce, lo script verrà chiuso.
In alternativa, puoi aggiungere istruzioni exit
nei possibili punti di errore:
command || exit 1
Commenti
Risposta
Puoi uscire da uno script in qualsiasi punto utilizzando la parola chiave exit
. Puoi anche specificare un codice di uscita per indicare ad altri programmi che o come lo script non è riuscito, ad es. exit 1
o exit 2
ecc. (Per convenzione, il codice di uscita 0 indica il successo e qualsiasi valore maggiore di 0 significa fallimento; tuttavia, anche per convenzione , i codici di uscita superiori a 127 sono riservati per la terminazione anomala (ad esempio tramite un segnale)).
La costruzione generica per uscire in caso di errore è
if [ failure condition ]; then exit n fi
con failure condition
e n
. Ma in scenari specifici puoi procedere diversamente. Ora, per il tuo caso, interpreto la tua domanda secondo cui se una qualsiasi delle cinque invocazioni di gksu
fallisce, allora intendi uscire. Un modo è utilizzare una funzione come questa
function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 }
e quindi richiamare il ciclo con try_command
.
Ci sono modi (più) avanzati o sofisticati per rispondere alla tua domanda. Tuttavia, la soluzione sopra è più accessibile ai principianti rispetto, ad esempio, alla soluzione di Stephane.
Risposta
attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done
exit
esce dallo script a meno che non venga chiamato in una subshell. Se quella parte dello script è in una subshell, ad esempio perché “è allinterno di (...)
o $(...)
o parte di una pipe-line , allora uscirà solo da quella subshell .
In tal caso, se vuoi che lo script esca oltre alla subshell, allora ” Dovrò chiamare exit
alluscita della subshell.
Ad esempio, qui con 2 livelli nidificati di subshell:
( life=hard output=$( echo blah [ "$life" = easy ] || exit 1 # exit subshell echo blih not run ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status echo not run either ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status
Può diventare più complicato se la subshell fa parte di una pipeline. bash
ha uno speciale $PIPESTATUS
array, simile a zsh
“s $pipestatus
che può aiutarti qui:
{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi
Rispondi
Trap eseguirà unazione alla ricezione di un segnale.
trap "echo EXIT; exit" 0 trap "echo HUP; exit" 1 trap "echo CTL-C; exit" 2 trap "echo QUIT; exit" 3 trap "echo ERR; exit" ERR n=0 until [ $n -ge 5 ] do n=$[$n+1] echo $n sleep 3 done
Eseguilo e lascialo uscire normalmente. Si intercetta al segnale 0.
EXIT
Eseguilo di nuovo e interrompi con ^ C. Si intercetta sia sul segnale 2 che sul segnale 0.
CTL-C EXIT
Uno stato di uscita diverso da zero verrà intercettato su ERR
ERR EXIT
Risposta
pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )&
set -e
(non conforme alla progettazione IMO). Tuttavia, ' non si applica qui. LOP vuole uscire dallo script dopo 5 tentativi falliti di eseguire il comando.set -e
è lunico modo che conosco per farlo.set -e
èsleep
(break
essendo un builtin speciale causa la chiusura dello script in caso di errore nella maggior parte delle shell, i comandi inif
o a sinistra di&&
non sono interessati daset -e
,n=...
potrebbe non riuscire sen
è di sola lettura, ma ciò uscirebbe dallo script anche senzaset -e
), quindi linterpretazione sembra piuttosto improbabile. Sono daccordo che la domanda sia formulata male.