Cum pot scrie un script shell care iese, dacă o parte a acestuia eșuează? De exemplu, dacă următorul fragment de cod nu reușește, atunci scriptul ar trebui să iasă.
n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3
Răspuns
O abordare ar fi să adăugați set -e
la începutul scriptului. Asta înseamnă (din help set
):
-e Exit immediately if a command exits with a non-zero status.
Deci, dacă oricare dintre comenzile dvs. eșuează, scriptul va ieși.
Alternativ, puteți adăuga instrucțiuni explicite exit
la posibilele puncte de eșec:
command || exit 1
Comentarii
Răspuns
Puteți ieși dintr-un script în orice loc folosind cuvântul cheie exit
. De asemenea, puteți specifica un cod de ieșire pentru a indica altor programe care sau cum a eșuat scriptul dvs., de ex. exit 1
sau exit 2
etc. (Prin convenție, codul de ieșire 0 este pentru succes și orice mai mare de 0 înseamnă eșec; totuși, de asemenea, prin convenție , codurile de ieșire de peste 127 sunt rezervate pentru terminarea anormală (de exemplu, printr-un semnal)).
Construcția generică de ieșire la eșec este
if [ failure condition ]; then exit n fi
cu failure condition
și n
adecvate. Dar, în scenarii specifice, puteți proceda diferit. Acum, pentru cazul dvs., vă interpretez întrebarea că, dacă oricare dintre cele cinci invocații ale gksu
eșuează, atunci doriți să ieșiți. O modalitate este de a utiliza o funcție ca aceasta
function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 }
și apoi, invocați bucla prin try_command
.
Există (mai) moduri avansate sau sofisticate de a vă adresa întrebării. Cu toate acestea, soluția de mai sus este mai accesibilă pentru începători decât, să zicem, soluția lui Stephane.
Răspuns
attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done
exit
iese din script dacă nu este apelat într-un subshell. Dacă acea parte a scriptului se află într-un sub-shell, de exemplu, deoarece se află în (...)
sau $(...)
sau o parte a unei conducte , atunci va ieși numai din acel subshell .
În acest caz, dacă doriți ca script să iasă în plus față de subshell, atunci dvs. ” Va trebui să apelez exit
la ieșirea acelui subshell.
De exemplu, aici cu 2 niveluri imbricate de 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
Poate deveni mai complicat dacă subshell-ul face parte dintr-o conductă. bash
are un tablou special $PIPESTATUS
, similar cu zsh
„s $pipestatus
unul care vă poate ajuta aici:
{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi
Răspuns
Trap va efectua o acțiune la primirea unui semnal.
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
Rulați acest lucru și lăsați-l să iasă normal. Acesta captează semnalul 0.
EXIT
Rulați-l din nou și întrerupeți-l cu ^ C. Captează atât semnalul 2, cât și semnalul 0.
CTL-C EXIT
O stare de ieșire diferită de zero va fi captată pe ERR
ERR EXIT
Răspuns
pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )&
set -e
. ' nu se aplică cu adevărat aici. OP dorește să părăsească scriptul după 5 încercări nereușite de a rula comanda.set -e
este singurul mod în care știu să fac asta.set -e
estesleep
(break
fiind un program special încorporat, scriptul va ieși în caz de eșec în majoritatea shell-urilor, comenzile din sau în stânga&&
nu sunt afectate deset -e
,n=...
ar putea eșua dacăn
este numai în citire, dar atunci ar ieși din script fărăset -e
și), astfel încât interpretarea sună destul de puțin probabil. Sunt de acord că întrebarea este slab formulată.