Risposte:
Un approccio sarebbe quello di aggiungere set -eall'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 exitistruzioni esplicite nei possibili punti di errore:
command || exit 1
set -eè l'unico modo che conosco per farlo.
set -esono sleep( breakessere un builtin speciale causerebbe la chiusura dello script in caso di fallimento nella maggior parte delle shell, i comandi dentro ifo 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 1o exit 2ecc. (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 conditione n. Ma in scenari specifici puoi procedere diversamente. Ora per il tuo caso interpreto la tua domanda che se una delle cinque invocazioni gksufallisce, 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
exitesce 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 exitl'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. bashha una speciale $PIPESTATUSmatrice, simile a zsh's $pipestatusuno 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.