Hur avslutar man ett skalskript om en del av det misslyckas?

Hur kan jag skriva ett skalskript som går ut om en del av det misslyckas? Om till exempel följande kodavsnitt misslyckas ska skriptet avslutas.

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

Svar

En metod skulle vara att lägga till set -e i början av ditt skript. Det betyder (från help set):

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

Så om några av dina kommandon misslyckas kommer skriptet att avslutas.

Alternativt kan du lägga till uttryckliga exit uttalanden vid möjliga felpunkter:

command || exit 1 

Kommentarer

  • Jag (och bash-wiki ) skulle hellre tänka folk på rätt felhantering istället för att använda funktionen (bruten av design IMO) set -e. Det gäller dock inte '. OP vill avsluta skriptet efter fem misslyckade försök att köra kommandot.
  • @St é phaneChazelas I won ' t argumentera med dig om det ' är trasigt, jag ' är säker på att du ' har rätt. Men OP frågade " Hur kan jag skriva ett skalskript som går ut, om en del av det misslyckas? ", vad gör dig tror att det ' handlar om att avslutas efter fem fel?
  • eftersom jag inte kan ' tänka på något annat sätt frågan kan tolkas.
  • @St é phaneChazelas du kan mycket väl ha rätt. Jag tolkade det bokstavligen: hur kan hela skriptet avslutas om någon del av det misslyckas. Och set -e är det enda sättet jag vet att göra det.
  • I det manuskriptet är kommandona som kan utlösa set -e är sleep (break att vara ett speciellt inbyggt skulle orsaka att skriptet avslutas vid fel i de flesta skal, kommandon i if eller till vänster om && påverkas inte av set -e, n=... kan misslyckas om n är skrivskyddad, men då går det ut från skriptet utan set -e, så att tolkning låter ganska osannolikt. Jag håller med om att frågan är dåligt formulerad.

Svar

Du kan avsluta ett skript var som helst med hjälp av nyckelordet exit. Du kan också ange en utgångskod för att ange för andra program att eller hur ditt skript misslyckades, t.ex. exit 1 eller exit 2 etc. (enligt konvention är utgångskod 0 för framgång och allt större än 0 betyder misslyckande, dock också enligt konvention , utgångskoder över 127 är reserverade för onormal avslutning (t.ex. av en signal)).

Den generiska konstruktionen för att avsluta vid fel är

if [ failure condition ]; then exit n fi 

med lämpliga failure condition och n. Men i specifika scenarier kan du gå annorlunda. Nu för ditt fall tolkar jag din fråga att om någon av de fem anropen av gksu misslyckas, så menar du att avsluta. Ett sätt är att använda en funktion som denna

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

och anropa sedan slingan med try_command.

Det finns (mer) avancerade eller sofistikerade sätt att ta itu med din fråga. Lösningen ovan är dock mer tillgänglig för nybörjare än, säg, Stephanes lösning.

Svar

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

exit avslutar skriptet såvida det inte kallas i en subshell. Om den delen av manuset finns i en subshell, till exempel för att den ligger inom (...) eller $(...) eller en del av en rörledning , så kommer det bara att avslutas det subshell .

I så fall, om du vill att script ska avslutas utöver subshell, så ” Jag måste ringa exit när det subshell avslutas.

Till exempel här med två kapslade nivåer av 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 

Det kan bli svårare om subshell är en del av en pipeline. bash har en speciell $PIPESTATUS matris, som liknar zsh ”s $pipestatus en som kan hjälpa dig här:

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

Svar

Trap utför en åtgärd efter mottagning av en signal.

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 

Kör detta och låt det gå ut normalt. Det fälls på signal 0.

EXIT 

Kör den igen och avbryt med ^ C. Den fälls in på både signal 2 och signal 0.

CTL-C EXIT 

En utgångsstatus som inte är noll fångas i ERR

ERR EXIT 

Svar

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

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *