Hoe sluit ik een shellscript af als een deel ervan mislukt?

Hoe kan ik een shellscript schrijven dat wordt afgesloten als een deel ervan faalt? Als het volgende codefragment bijvoorbeeld mislukt, moet het script worden afgesloten.

n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3 

Answer

Een benadering zou zijn om set -e toe te voegen aan het begin van uw script. Dat betekent (van help set):

 -e Exit immediately if a command exits with a non-zero status. 

Dus als een van je commandos mislukt, wordt het script afgesloten.

U kunt ook expliciete exit -instructies toevoegen aan de mogelijke foutpunten:

command || exit 1 

Reacties

  • Ik (en de bash wiki ) zou liever hebben dat mensen nadenken over de juiste foutafhandeling in plaats van de functie (broken by design IMO) set -e te gebruiken. Het is hier echter niet ' echt van toepassing. Het OP wil het script verlaten na 5 mislukte pogingen om de opdracht uit te voeren.
  • @St é phaneChazelas Ik heb ' ik ruzie met je over de vraag of het ' kapot is, ik ' weet zeker dat je ' re rechts. Het OP vroeg echter " Hoe kan ik een shellscript schrijven dat wordt afgesloten als een deel ervan mislukt? ", wat maakt jou denk dat het ' s over afsluiten na 5 mislukkingen?
  • omdat ik ' geen andere manier kan bedenken om de vraag kan worden geïnterpreteerd.
  • @St é phaneChazelas je hebt misschien gelijk. Ik heb het letterlijk geïnterpreteerd: hoe kan het hele script worden afgesloten als een deel ervan faalt. En set -e is de enige manier om dat te doen.
  • In dat scriptfragment, de commandos die set -e is sleep (break als een speciale ingebouwde versie zou het script in de meeste shells afsluiten bij een fout, commandos in if of links van && worden niet beïnvloed door set -e, n=... kan mislukken als n alleen-lezen is, maar dan zou het script ook zonder set -e worden afgesloten), zodat interpretatie klinkt nogal onwaarschijnlijk. Ik ben het ermee eens dat de vraag slecht is geformuleerd.

Antwoord

Je kunt een script op elke plek verlaten met het trefwoord exit. U kunt ook een exitcode opgeven om aan andere programmas aan te geven dat of hoe uw script is mislukt, bijv. exit 1 of exit 2 enz. (Volgens afspraak is exitcode 0 voor succes en alles groter dan 0 duidt op een mislukking, maar ook volgens afspraak , exitcodes boven 127 zijn gereserveerd voor abnormale beëindiging (bijv. door een signaal)).

De algemene constructie om af te sluiten bij een fout is

if [ failure condition ]; then exit n fi 

met geschikte failure condition en n. Maar in specifieke scenarios kunt u anders te werk gaan. Voor jouw geval interpreteer ik je vraag dat als een van de vijf aanroepen van gksu mislukt, je wilt afsluiten. Een manier is om een functie als deze te gebruiken

function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 } 

en vervolgens de lus aan te roepen door try_command.

Er zijn (meer) geavanceerde of geavanceerde manieren om uw vraag te beantwoorden. De bovenstaande oplossing is echter toegankelijker voor beginners dan bijvoorbeeld de oplossing van Stephane.

Antwoord

attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done 

exit verlaat het script tenzij het wordt aangeroepen in een subshell. Als dat deel van het script zich in een subshell bevindt, bijvoorbeeld omdat het “binnen (...) of $(...) of een deel van een pijplijn is , dan zal het alleen die subshell verlaten.

In dat geval, als je wilt dat het script wordt afgesloten naast de subshell, dan ” Ik zal exit moeten aanroepen bij het afsluiten van die subshell.

Bijvoorbeeld hier met 2 geneste niveaus van 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 

Het kan lastiger worden als de subshell deel uitmaakt van een pijplijn. bash heeft een speciale $PIPESTATUS array, vergelijkbaar met zsh “s $pipestatus een die u hier kan helpen:

{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi 

Antwoord

Trap voert een actie uit na ontvangst van een signaal.

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 

Voer dit uit en laat het normaal afsluiten. Het wordt vastgehouden op signaal 0.

EXIT 

Voer het opnieuw uit en onderbreek het met ^ C. Het valt op zowel signaal 2 als signaal 0.

CTL-C EXIT 

Een exitstatus die niet gelijk is aan nul zal vastlopen bij ERR

ERR EXIT 

Antwoord

pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )& 

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *