Risposte:
Un approccio sarebbe quello di aggiungere set -e
all'inizio della tua sceneggiatura. 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, è possibile aggiungere exit
istruzioni esplicite nei possibili punti di errore:
command || exit 1
set -e
è l'unico modo che conosco per farlo.
set -e
sono sleep
( break
essere un builtin speciale causerebbe la chiusura dello script in caso di fallimento nella maggior parte delle shell, i comandi dentro if
o alla sinistra di &&
non sono interessati set -e
, n=...
potrebbero fallire se n
è di sola lettura, ma poi anche questo uscirebbe dalla sceneggiatura set -e
), quindi l'interpretazione sembra abbastanza improbabile. Sono d'accordo che la domanda sia formulata male.
Puoi uscire da uno script in qualsiasi luogo usando la parola chiave exit
. Puoi anche specificare un codice di uscita per indicare ad altri programmi che o come lo script è fallito, ad esempio exit 1
o exit 2
ecc. (Per convenzione, il codice di uscita 0 ha esito positivo e qualsiasi cosa maggiore di 0 indica un errore; tuttavia, anche per convenzione, esci i codici superiori a 127 sono riservati per terminazioni anomale (ad es. mediante un segnale)).
La costruzione generica per uscire in caso di fallimento è
if [ failure condition ]; then
exit n
fi
con adatto failure condition
e n
. Ma in scenari specifici puoi procedere diversamente. Ora per il tuo caso interpreto la tua domanda che se una delle cinque invocazioni gksu
fallisce, allora intendi uscire. Un modo è usare 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, invoca il loop di try_command
.
Esistono (più) modi avanzati o sofisticati per affrontare la tua domanda. Tuttavia, la soluzione sopra è più accessibile ai principianti rispetto, per esempio, alla soluzione di Stephane.
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 si trova in una subshell, ad esempio perché è all'interno (...)
o $(...)
o parte di una pipe-line, allora uscirà solo da quella subshell .
In tal caso, se si desidera che lo script esca in aggiunta alla subshell, è necessario richiamare exit
l'uscita della subshell.
Ad esempio, qui con 2 livelli nidificati di subshells:
(
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 una speciale $PIPESTATUS
matrice, simile a zsh
's $pipestatus
uno che può aiutare qui:
{
echo foo
exit 1
echo bar
} | wc -c
subshell_ret=${PIPESTATUS[0]}
if [ "$subshell_ret" -ne 0 ]; then
exit "$subshell_ret"
fi
La trap eseguirà un'azione 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
Esegui questo e lascialo uscire normalmente. Intrappola sul segnale 0.
EXIT
Eseguire di nuovo e interrompere con ^ C. Intrappola sia il segnale 2 che il segnale 0.
CTL-C
EXIT
Uno stato di uscita diverso da zero eseguirà il trap su ERR
ERR
EXIT
set -e
. In realtà non si applica qui. L'OP vuole uscire dallo script dopo 5 tentativi falliti di eseguire il comando.