Prozesse können den _exit()
Systemaufruf (unter Linux, siehe auch exit_group()
) mit einem Integer-Argument aufrufen , um einen Exit-Code an das übergeordnete Element zu melden. Obwohl es eine ganze Zahl ist, werden nur die 8 niedrigstwertigen Bits an die Mutter verfügbar sind (Ausnahme das ist , wenn unter Verwendung von waitid()
in den übergeordneten oder Handler auf SIGCHLD diesen Code abgerufen werden , wenn auch nicht auf Linux).
Das übergeordnete Element führt in der Regel ein wait()
oder aus waitpid()
, um den Status des untergeordneten Elements als Ganzzahl abzurufen (obwohl auch eine waitid()
etwas andere Semantik verwendet werden kann).
Unter Linux und die meisten Unix - Varianten, wenn der Prozess normal beendet, die Bits 8 bis 15 der Statusnummer wird den Exit - Code enthält , wie sie weitergegeben exit()
. Wenn nicht, dann enthalten die 7 niedrigstwertigen Bits (0 bis 6) die Signalnummer und Bit 7 wird gesetzt, wenn ein Kern ausgegeben wurde.
perl
ist $?
beispielsweise enthält die Zahl ist, wie sie durch waitpid()
:
$ perl -e 'system q(kill $$); printf "%04x\n", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04x\n", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04x\n", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Bourne-ähnliche Shells geben auch den Exit-Status des letzten Ausführungsbefehls in ihrer eigenen $?
Variablen an. Es enthält jedoch nicht direkt die Zahl, die von zurückgegeben wurde waitpid()
, sondern eine Transformation darauf und unterscheidet sich zwischen den Shells.
Allen Shells ist gemeinsam, dass sie $?
die niedrigsten 8 Bits des Exit-Codes (die Nummer, an die übergeben wird exit()
) enthalten, wenn der Prozess normal beendet wird.
Der Unterschied besteht darin, dass der Prozess durch ein Signal beendet wird. In allen Fällen, und das ist für POSIX erforderlich, ist die Zahl größer als 128. POSIX gibt nicht an, wie hoch der Wert sein darf. In der Praxis $?
enthalten die untersten 7 Bits aller mir bekannten Bourne-ähnlichen Shells die Signalnummer. Aber wo n
ist die Signalnummer,
in Asche, zsh, pdksh, schlag, die Bourne - Shell $?
ist 128 + n
. Was das bedeutet , ist , dass in den Schalen, wenn Sie eine bekommen $?
von 129
, Sie wissen nicht, ob es daran , dass der Prozess mit verlassen , exit(129)
oder ob es durch das Signal getötet wurde 1
( HUP
auf den meisten Systemen). Das Grundprinzip ist jedoch, dass Shells, wenn sie sich selbst beenden, standardmäßig den Beendigungsstatus des zuletzt beendeten Befehls zurückgeben. Wenn Sie sicherstellen $?
, dass der Wert niemals größer als 255 ist, können Sie einen konsistenten Beendigungsstatus festlegen:
$ bash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
bash: line 1: 16720 Terminated sh -c "kill \$\$"
8f # 128 + 15
$ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
bash: line 1: 16726 Terminated sh -c "kill \$\$"
8f # here that 0x8f is from a exit(143) done by bash. Though it's
# not from a killed process, that does tell us that probably
# something was killed by a SIGTERM
ksh93
, $?
Ist 256 + n
. Das bedeutet, dass Sie aus einem Wert von $?
zwischen einem getöteten und einem nicht getöteten Prozess unterscheiden können. Neuere Versionen von beenden sich mit demselben Signal ksh
, wenn sie $?
größer als 255 waren, um dem übergeordneten Element denselben Beendigungsstatus melden zu können. Das klingt zwar nach einer guten Idee, bedeutet aber, dass ksh
ein zusätzlicher Core-Dump generiert wird (der andere wird möglicherweise überschrieben), wenn der Prozess durch ein Core-Generierungssignal beendet wurde:
$ ksh -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
ksh: 16828: Terminated
10f # 256 + 15
$ ksh -c 'sh -c "kill -ILL \$\$"; exit'; printf '%x\n' "$?"
ksh: 16816: Illegal instruction(coredump)
Illegal instruction(coredump)
104 # 256 + 15, ksh did indeed kill itself so as to report the same
# exit status as sh. Older versions of `ksh93` would have returned
# 4 instead.
Man könnte sogar sagen, dass es einen Fehler gibt, ksh93
der sich selbst tötet, selbst wenn $?
er return 257
von einer Funktion ausgeführt wird:
$ ksh -c 'f() { return "$1"; }; f 257; exit'
zsh: hangup ksh -c 'f() { return "$1"; }; f 257; exit'
# ksh kills itself with a SIGHUP so as to report a 257 exit status
# to its parent
yash
. yash
bietet einen Kompromiss. Es kehrt zurück 256 + 128 + n
. Das heißt, wir können auch zwischen einem abgebrochenen und einem ordnungsgemäß abgebrochenen Prozess unterscheiden. Und beim Verlassen meldet es sich, 128 + n
ohne sich selbst umbringen zu müssen, und welche Nebenwirkungen es haben kann.
$ yash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
18f # 256 + 128 + 15
$ yash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
8f # that's from a exit(143), yash was not killed
Um das Signal aus dem Wert von zu erhalten $?
, können Sie auf tragbare Weise Folgendes verwenden kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(aus Gründen der Portabilität sollten Sie niemals Signalnummern verwenden, sondern nur Signalnamen)
An den Nicht-Bourne-Fronten:
csh
/ tcsh
und fish
wie die Bourne-Shell, mit der Ausnahme, dass sich der Status in $status
statt befindet $?
(beachten Sie, dass dies zsh
auch $status
für die Kompatibilität mit csh
(zusätzlich zu $?
) festgelegt ist).
rc
: der Exit-Status ist auch in $status
, aber wenn diese Variable von einem Signal getötet wird, enthält sie den Namen des Signals (wie sigterm
oder sigill+core
wenn ein Core generiert wurde) anstelle einer Zahl, was ein weiterer Beweis für das gute Design dieser Shell ist .
es
. Der Exit-Status ist keine Variable. Wenn Sie sich darum kümmern, führen Sie den Befehl wie folgt aus:
status = <={cmd}
die wird eine Nummer sigterm
oder sigsegv+core
wie in zurückgeben rc
.
Vielleicht für die Vollständigkeit, sollten wir erwähnen , zsh
‚s $pipestatus
und bash
‘ s - $PIPESTATUS
Arrays , die den Exit - Status der Komponenten der letzten Pipeline enthalten.
Und auch der Vollständigkeit return
halber , wenn es um Shell-Funktionen und Quelldateien geht, kehren Funktionen standardmäßig mit dem Exit-Status des letzten Befehlslaufs zurück, können aber mit dem eingebauten Befehl auch explizit einen Return-Status setzen. Und wir sehen hier einige Unterschiede:
bash
und mksh
(seit R41 wird anscheinend absichtlich eine Regression ^ Wchange eingeführt ) wird die Zahl (positiv oder negativ) auf 8 Bits abgeschnitten. So zum Beispiel return 1234
wird festgelegt $?
auf 210
, return -- -1
wird eingestellt $?
auf 255.
zsh
und pdksh
(und andere Ableitungen als mksh
) erlauben jede vorzeichenbehaftete 32-Bit-Dezimalzahl (-2 31 bis 2 31 -1) (und kürzen die Zahl auf 32 Bit ).
ash
und yash
erlaube eine beliebige positive ganze Zahl von 0 bis 2 31 -1 und gebe einen Fehler für eine beliebige Zahl davon zurück.
ksh93
Für return 0
die return 320
Einstellung $?
wie sie ist, aber für alles andere, kürzen Sie auf 8 Bits. Beachten Sie, wie bereits erwähnt, dass sich das Zurückgeben einer Zahl zwischen 256 und 320 ksh
beim Beenden selbst töten kann.
rc
und es
erlauben, alles auch Listen zurückzugeben.
Beachten Sie auch, dass einige Shells auch spezielle Werte von $?
/ verwenden $status
, um einige Fehlerzustände zu melden, die nicht den Beendigungsstatus eines Prozesses darstellen, z. B. 127
oder 126
für einen Befehl, der nicht gefunden oder nicht ausführbar ist (oder einen Syntaxfehler in einer Quelldatei) ...
killall myScript
Arbeiten, daher ist die Rückgabe des killall (und nicht des Skripts!) 0. Sie könnten einkill -x $$
[x als Signalnummer setzen und $$ normalerweise durch die Shell auf die PID des Skripts erweitern (funktioniert in sh, bash, ...)] innerhalb des Skripts und testen Sie dann, was der Ausgangskern war.