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
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 $? )&
set -e
. Det gäller dock inte '. OP vill avsluta skriptet efter fem misslyckade försök att köra kommandot.set -e
är det enda sättet jag vet att göra det.set -e
ärsleep
(break
att vara ett speciellt inbyggt skulle orsaka att skriptet avslutas vid fel i de flesta skal, kommandon iif
eller till vänster om&&
påverkas inte avset -e
,n=...
kan misslyckas omn
är skrivskyddad, men då går det ut från skriptet utanset -e
, så att tolkning låter ganska osannolikt. Jag håller med om att frågan är dåligt formulerad.