Hvordan kan jeg skrive et shell-script, der afsluttes, hvis en del af det fejler? For eksempel, hvis følgende kodestykke fejler, skal scriptet afslutte.
n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3
Svar
En tilgang ville være at tilføje set -e
til begyndelsen af dit script. Det betyder (fra help set
):
-e Exit immediately if a command exits with a non-zero status.
Så hvis nogen af dine kommandoer mislykkes, afslutter scriptet.
Alternativt kan du tilføje eksplicit exit
udsagn ved de mulige fejlpunkter:
command || exit 1
Kommentarer
Svar
Du kan afslutte et script hvor som helst ved hjælp af nøgleordet exit
. Du kan også angive en udgangskode for at angive for andre programmer, at eller hvordan dit script mislykkedes, f.eks. exit 1
eller exit 2
osv. (Af konvention er exit kode 0 for succes, og alt større end 0 betyder fiasko, dog også ved konvention , udgangskoder over 127 er reserveret til unormal afslutning (f.eks. ved et signal)).
Den generiske konstruktion til afslutning ved fejl er
if [ failure condition ]; then exit n fi
med passende failure condition
og n
. Men i specifikke scenarier kan du gå anderledes ud. Nu for din sag fortolker jeg dit spørgsmål om, at hvis nogen af de fem påkaldelser af gksu
mislykkes, så mener du at afslutte. En måde er at bruge en funktion som denne
function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 }
og derefter påkalde sløjfen ved at try_command
.
Der er (mere) avancerede eller sofistikerede måder at behandle dit spørgsmål på. Ovenstående løsning er dog mere tilgængelig for begyndere end, for eksempel, Stephanes løsning.
Svar
attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done
exit
afslutter scriptet, medmindre det kaldes i en subshell. Hvis den del af scriptet er i en subshell, for eksempel fordi den “er inden for (...)
eller $(...)
eller en del af en rørledning , så afslutter det kun den subshell .
I så fald, hvis du vil have scriptet ud foruden subshell, så ” Jeg skal ringe til exit
når denne subshell afsluttes.
For eksempel her med 2 indlejrede niveauer af 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 blive vanskeligere, hvis subshell er en del af en pipeline. bash
har et specielt $PIPESTATUS
array svarende til zsh
“s $pipestatus
en der kan hjælpe dig her:
{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi
Svar
Trap udfører en handling efter modtagelse af et 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 dette og lad det afslutte normalt. Det fælder på signal 0.
EXIT
Kør det igen og afbryd med ^ C. Det fælder både signal 2 og signal 0.
CTL-C EXIT
En udgangsstatus, der ikke er nul, fanges 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ælder dog ikke '. OPen ønsker at afslutte scriptet efter 5 mislykkede forsøg på at køre kommandoen.set -e
er den eneste måde, jeg ved det på.set -e
ersleep
(break
at være en speciel indbygget ville få scriptet til at afslutte ved fejl i de fleste skaller, kommandoer iif
eller til venstre for&&
påvirkes ikke afset -e
,n=...
kunne mislykkes, hvisn
er skrivebeskyttet, men så ville det også afslutte scriptet udenset -e
, så fortolkning lyder ret usandsynligt. Jeg er enig i, at spørgsmålet er dårligt formuleret.