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
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 $? )&
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.set -e
is de enige manier om dat te doen.set -e
issleep
(break
als een speciale ingebouwde versie zou het script in de meeste shells afsluiten bij een fout, commandos inif
of links van&&
worden niet beïnvloed doorset -e
,n=...
kan mislukken alsn
alleen-lezen is, maar dan zou het script ook zonderset -e
worden afgesloten), zodat interpretatie klinkt nogal onwaarschijnlijk. Ik ben het ermee eens dat de vraag slecht is geformuleerd.