Jak ukončit shell skript, pokud jedna jeho část selže?

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

  • Já (a bash wiki ) bych raději, aby si lidé mysleli na správné zacházení s chybami místo použití 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.
  • @St é phaneChazelas vyhrál jsem ' t s tebou polemizuje o tom, zda je to ' s nefunkční, jsem si ' jist, že ' máte pravdu. OP se však zeptal " Jak mohu napsat shell skript, který se ukončí, pokud jeho část selže? ", co vás dělá myslíte, že ' jde o ukončení po 5 selháních?
  • protože nemohu ' přemýšlet o žádném jiném způsobu otázku lze interpretovat.
  • @St é phaneChazelas můžete mít pravdu. Interpretoval jsem to doslovně: jak může celý skript ukončit, pokud některá jeho část selže. A set -e je jediný způsob, jak to vím.
  • V tomto fragmentu skriptu jsou příkazy, které by mohly spustit set -e je sleep (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 v if nebo nalevo od && nejsou ovlivněny set -e, n=... může selhat, pokud je n jen pro čtení, ale to by ukončilo skript i bez set -e), takže interpretace zní docela nepravděpodobně. Souhlasím, že otázka je špatně formulovaná.

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 $? )& 

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *