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 -eon ainoa tapa, jolla tiedän sen tekevän.set -eonsleep(breakerityinen sisäänrakennettu komento lopettaa vian useimmissa kuoreissa, komennot iv id =set -e,n=...tai&&-kohdan vasemmalla puolella