Kuinka voin kirjoittaa komentosarjan, joka poistuu, jos yksi sen osa epäonnistuu? Esimerkiksi, jos seuraava koodinpätkä epäonnistuu, komentosarjan pitäisi poistua.
n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3
Vastaa
Yksi tapa olisi lisätä set -e
komentosarjan alkuun. Tämä tarkoittaa (mistä: help set
):
-e Exit immediately if a command exits with a non-zero status.
Joten jos jokin komennoista epäonnistuu, komentosarja poistuu.
Vaihtoehtoisesti voit lisätä eksplisiittisiä exit
-lausekkeita mahdollisiin vikapisteisiin:
command || exit 1
Kommentit
voi epäonnistua, jos n
on vain luku -muodossa, mutta se sulkisi komentosarjan ilman set -e
), niin että tulkinta kuulostaa melko epätodennäköiseltä. Olen samaa mieltä siitä, että kysymys on muotoiltu huonosti.
Vastaa
Voit poistua komentosarjasta missä tahansa avainsanalla exit
. Voit myös määrittää poistumiskoodin osoittamaan muille ohjelmille, että komentosarjasi epäonnistui tai kuinka exit 1
tai exit 2
jne. (Tavanomaisesti poistumistunnus 0 on menestys ja mikä tahansa suurempi kuin 0 tarkoittaa epäonnistumista; kuitenkin myös sopimuksen mukaan , poistumiskoodit, jotka ovat yli 127, on varattu epänormaalille päättämiselle (esim. signaalilla).
Yleinen rakenne poistumiseen vikaantumisen yhteydessä on
if [ failure condition ]; then exit n fi
sopivilla failure condition
ja n
kanssa. Mutta tietyissä tilanteissa voit edetä toisin. Tapauksessasi tulkitsen kysymyksesi, että jos jokin viidestä gksu
-kutsusta epäonnistuu, tarkoitat lopettaa. Yksi tapa on käyttää tällaista toimintoa
function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 }
ja sitten kutsua silmukka try_command
.
On (enemmän) edistyneempiä tai hienostuneempia tapoja vastata kysymykseesi. Yllä oleva ratkaisu on kuitenkin helpompi aloittelijoille kuin Stephanen ratkaisu.
Vastaa
attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done
exit
sulkee komentosarjan, ellei sitä kutsuta alikuoressa. Jos komentosarjan kyseinen osa on alikuoressa, esimerkiksi koska se on (...)
tai $(...)
tai putkilinjan sisällä , niin se poistuu vain kyseisestä alikuoresta .
Jos siinä tapauksessa haluat komentosarjan poistuvan alikuoren lisäksi, sinä ” Minun täytyy kutsua exit
, kun kyseinen alikuori poistuu.
Esimerkiksi täällä, jossa on 2 sisäkkäistä alihakutasoa:
( 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
Siitä voi tulla hankalampaa, jos alikuori on osa putkistoa. bash
-laitteessa on erityinen $PIPESTATUS
-taulukko, joka on samanlainen kuin zsh
”s $pipestatus
joka voi auttaa sinua tässä:
{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi
vastaus
Trap suorittaa toiminnon vastaanotettuaan signaalin.
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
Suorita tämä ja anna sen poistua normaalisti. Se tarttuu signaaliin 0.
EXIT
Suorita se uudelleen ja keskeytä painikkeella ^ C. Se tarttuu sekä signaaliin 2 että signaaliin 0.
CTL-C EXIT
Poistumistila, joka ei ole nolla, tarttuu ERR: ään
ERR EXIT
Vastaa
pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )&
set -e
-ominaisuutta. Se ei kuitenkaan ' sovellu tähän. OP haluaa lopettaa komentosarjan viiden epäonnistuneen komennon suorittamisen jälkeen.set -e
on ainoa tapa, jolla tiedän sen tekevän.set -e
onsleep
(break
erityinen sisäänrakennettu komento lopettaa vian useimmissa kuoreissa, komennot iv id =set -e
,n=...
tai&&
-kohdan vasemmalla puolella