Jak mohu napsat shell skript, který se ukončí, pokud jeho část selže? Pokud například selže následující fragment kódu, měl by se skript ukončit.
n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3
Odpovědět
Jedním z přístupů by bylo přidání set -e
na začátek skriptu. To znamená (z help set
):
-e Exit immediately if a command exits with a non-zero status.
Takže pokud některý z vašich příkazů selže, skript se ukončí.
Alternativně můžete přidat explicitní exit
prohlášení v možných bodech selhání:
command || exit 1
Komentáře
Odpovědět
Pomocí klíčového slova můžete skript kdykoli ukončit exit
. Můžete také zadat kód ukončení, abyste ostatním programům naznačili, že nebo jak selhal váš skript, např. exit 1
nebo exit 2
atd. (Podle konvence je výstupní kód 0 pro úspěch a cokoli větší než 0 znamená selhání; nicméně také podle konvence , kódy ukončení nad 127 jsou vyhrazeny pro abnormální ukončení (např. signálem)).
Obecná konstrukce pro ukončení při selhání je
if [ failure condition ]; then exit n fi
vhodnými failure condition
a n
. Ve specifických scénářích však můžete postupovat odlišně. Nyní pro váš případ interpretuji vaši otázku, že pokud kterékoli z pěti vyvolání gksu
selže, máte na mysli ukončení. Jedním ze způsobů je použití této funkce
function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 }
a potom vyvolání smyčky pomocí try_command
.
Existují (více) pokročilé nebo sofistikované způsoby, jak řešit vaši otázku. Výše uvedené řešení je však přístupnější pro začátečníky než, řekněme, Stephanovo řešení.
Odpověď
attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done
exit
ukončí skript, pokud není volán v subshellu. Pokud je tato část skriptu v subshellu, například proto, že je v (...)
nebo $(...)
nebo v části potrubí , pak opustí pouze tuto subshellu .
V takovém případě, pokud chcete, aby kromě subshellu byl ukončen skript , pak vy “ Po ukončení této subshellu budu muset zavolat exit
.
Například zde se 2 vnořenými úrovněmi 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
Pokud je subshell součástí potrubí, může být složitější. bash
má speciální $PIPESTATUS
pole podobné zsh
„s $pipestatus
ten, který vám zde může pomoci:
{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi
odpověď
Trap provede akci po přijetí signálu.
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
Spustit to a nechat jej normálně opustit. Zachytí signál 0.
EXIT
Spusťte jej znovu a přerušte jej ^ C. Zachytí signál 2 i signál 0.
CTL-C EXIT
Nenulový stav ukončení bude zachycovat ERR
ERR EXIT
Odpovědět
pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )&
set -e
funkce (rozbitá podle designu IMO). ' to zde ale opravdu neplatí. OP chce skript ukončit po 5 neúspěšných pokusech o spuštění příkazu.set -e
je jediný způsob, jak to vím.set -e
jesleep
(break
speciální vestavění by způsobilo, že by se skript při selhání většiny prostředí ukončil, příkazy vif
nebo nalevo od&&
nejsou ovlivněnyset -e
,n=...
může selhat, pokud jen
jen pro čtení, ale to by ukončilo skript i bezset -e
), takže interpretace zní docela nepravděpodobně. Souhlasím, že otázka je špatně formulovaná.