Hvordan kan jeg skrive et skallskript som går ut, hvis en del av det mislykkes? Hvis for eksempel kodebiten mislykkes, skal skriptet avsluttes.
n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3
Svar
En tilnærming ville være å legge til set -e
i begynnelsen av skriptet. Det betyr (fra help set
):
-e Exit immediately if a command exits with a non-zero status.
Så hvis noen av kommandoene dine mislykkes, avsluttes skriptet.
Alternativt kan du legge til eksplisitte exit
utsagn ved mulige feilpunkter:
command || exit 1
Kommentarer
Svar
Du kan avslutte et skript hvor som helst ved hjelp av nøkkelordet exit
. Du kan også spesifisere en utgangskode for å indikere for andre programmer at eller hvordan skriptet ditt mislyktes, f.eks. exit 1
eller exit 2
osv. (Etter konvensjon er utgangskode 0 for suksess og alt større enn 0 betyr feil, men også etter konvensjon , er utgangskoder over 127 reservert for unormal avslutning (f.eks. av et signal)).
Den generiske konstruksjonen for å avslutte ved feil er
if [ failure condition ]; then exit n fi
med passende failure condition
og n
. Men i spesifikke scenarier kan du gå annerledes. Nå for din sak tolker jeg spørsmålet ditt om at hvis noen av de fem anropene til gksu
mislykkes, så mener du å avslutte. En måte er å bruke en funksjon 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 deretter påkalle sløyfen ved å try_command
.
Det er (mer) avanserte eller sofistikerte måter å håndtere spørsmålet ditt på. Løsningen ovenfor er imidlertid mer tilgjengelig for nybegynnere enn 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
avslutter skriptet med mindre det kalles i en subshell. Hvis den delen av skriptet er i en subshell, for eksempel fordi den ligger innenfor (...)
eller $(...)
eller en del av en rørledning , så vil den bare avslutte den underskallen .
I så fall, hvis du vil at skriptet skal avsluttes i tillegg til underskallet, så Jeg må ringe exit
når det subshell avsluttes.
For eksempel, her med to nestede 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 vanskeligere hvis subshell er en del av en rørledning. bash
har en spesiell $PIPESTATUS
matrise, som zsh
«s $pipestatus
en som kan hjelpe deg 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 vil utføre en handling etter mottak av 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
Kjør dette og la det gå normalt. Det feller på signal 0.
EXIT
Kjør den igjen og avbryt med ^ C. Den feller både signal 2 og signal 0.
CTL-C EXIT
En utgangsstatus som ikke er null, blir fanget 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 gjelder ikke ' her. OP-en vil avslutte skriptet etter 5 mislykkede forsøk på å kjøre kommandoen.set -e
er den eneste måten jeg vet å gjøre det.set -e
ersleep
(break
å være en spesiell innebygd ville føre til at skriptet avsluttes ved feil i de fleste skjell, kommandoer iif
eller til venstre for&&
påvirkes ikke avset -e
,n=...
kan mislykkes hvisn
er skrivebeskyttet, men da vil det også gå ut av skriptet utenset -e
), slik at tolkning høres ganske usannsynlig ut. Jeg er enig i at spørsmålet er dårlig formulert.