Hoe afsluiten als een opdracht is mislukt?

Ik ben een noob in shell-scripting. Ik wil een bericht afdrukken en mijn script afsluiten als een opdracht mislukt. Ik heb geprobeerd:

my_command && (echo 'my_command failed; exit)

maar het werkt niet. Het blijft de instructies uitvoeren die op deze regel in het script volgen. Ik gebruik Ubuntu en bash.


Antwoord 1, autoriteit 100%

Probeer:

my_command || { echo 'my_command failed' ; exit 1; }

Vier wijzigingen:

  • Verander &&in ||
  • Gebruik { }in plaats van ( )
  • Introduceer ;na exiten
  • spaties na {en voor }

Omdat je het bericht wilt afdrukken en alleen wilt afsluiten als de opdracht mislukt (afsluiten met een waarde die niet nul is), heb je een ||nodig en geen &&.

cmd1 && cmd2

voert cmd2uit wanneer cmd1slaagt (eindwaarde 0). Waar als

cmd1 || cmd2

voert cmd2uit wanneer cmd1faalt (eindwaarde niet nul).

Als u ( )gebruikt, wordt de opdracht erin uitgevoerd in een sub-shellen wordt een exitaangeroepen vanuit daar zorgt ervoor dat je de sub-shell verlaat en niet je originele shell, dus de uitvoering gaat verder in je originele shell.

Om dit te verhelpen, gebruikt u { }

De laatste twee wijzigingen zijn vereist voor bash.


Antwoord 2, autoriteit 32%

De andere antwoorden hebben de directe vraag goed beantwoord, maar misschien ben je ook geïnteresseerd in het gebruik van set -e. Daardoor zal elk commando dat faalt (buiten specifieke contexten zoals iftests) ervoor zorgen dat het script wordt afgebroken. Voor bepaalde scripts is het erg handig.


Antwoord 3, autoriteit 18%

Als je dat gedrag wilt voor alle commando’s in je script, voeg dan gewoon

set -e 
set -o pipefail

aan het begin van het script. Dit paar opties vertelt de bash-interpreter om af te sluiten wanneer een opdracht terugkeert met een afsluitcode die niet nul is. (Voor meer details over waarom pipefailnodig is, zie http:/ /petereisentraut.blogspot.com/2010/11/pipefail.html)

Hiermee kunt u echter geen exit-bericht afdrukken.


Antwoord 4, autoriteit 15%

Houd er rekening mee dat de exit-status van elke opdracht wordt opgeslagen in de shell-variabele $?, die je direct kunt controleren nadat je de opdracht hebt uitgevoerd. Een status die niet nul is, duidt op een fout:

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi

Antwoord 5, autoriteit 3%

Ik heb het volgende idioom gehackt:

echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi
echo "Done."

Laat elke opdracht voorafgaan door een informatieve echo en volg elke opdracht met diezelfde
if [ $? -ne 0 ];...regel. (Natuurlijk kunt u die foutmelding bewerken als u dat wilt.)


Antwoord 6, autoriteit 2%

Op voorwaarde dat my_commandcanoniek is ontworpen, ie0 retourneert als het lukt, dan is &&precies het tegenovergestelde van wat je wilt. Je wilt ||.

Houd er rekening mee dat (me niet goed lijkt in bash, maar ik kan het niet proberen vanaf waar ik ben. Vertel het me.

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}

Antwoord 7

U kunt ook gebruiken, als u de exit-foutstatus wilt behouden, en een leesbaar bestand hebben met één opdracht per regel:

my_command1 || exit $?
my_command2 || exit $?

Hiermee wordt echter geen extra foutbericht afgedrukt. Maar in sommige gevallen wordt de fout toch afgedrukt door de mislukte opdracht.


Antwoord 8

De ingebouwde trapshell maakt het opvangen van signalen en andere nuttige voorwaarden mogelijk, waaronder mislukte uitvoering van opdrachten (d.w.z. een retourstatus die niet nul is). Dus als je niet expliciet de retourstatus van elk afzonderlijk commando wilt testen, kun je trap "your shell code" ERRzeggen en de shell-code wordt uitgevoerd wanneer een commando een niet-nul status retourneert . Bijvoorbeeld:

trap "echo script failed; exit 1" ERR

Merk op dat net als bij andere gevallen van het opvangen van mislukte opdrachten, pijplijnen een speciale behandeling nodig hebben; het bovenstaande zal false | true.


Antwoord 9

Het rechtstreeks gebruiken van exitkan lastig zijn omdat het script van andere plaatsen afkomstig kan zijn (bijv. van terminal). Ik gebruik in plaats daarvan liever een subshell met set -e(plus fouten zouden in cerr moeten staan, niet in cout):

set -e
ERRCODE=0
my_command || ERRCODE=$?
test $ERRCODE == 0 ||
    (>&2 echo "My command failed ($ERRCODE)"; exit $ERRCODE)

Other episodes