GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Standard-Exit-Code, wenn der Prozess beendet wird?

Wenn ein Prozess mit einem handhabbaren Signal wie SIGINT beendet wird oder SIGTERM aber es verarbeitet das Signal nicht, wie lautet der Exit-Code des Prozesses?

Was ist mit nicht handhabbaren Signalen wie SIGKILL ?

Soweit ich das beurteilen kann, wird ein Prozess mit SIGINT beendet führt wahrscheinlich zum Exit-Code 130 , aber würde das je nach Kernel- oder Shell-Implementierung variieren?

$ cat myScript
#!/bin/bash
sleep 5
$ ./myScript
<ctrl-c here>
$ echo $?
130

Ich bin mir nicht sicher, wie ich die anderen Signale testen würde…

$ ./myScript &
$ killall myScript
$ echo $?
0  # duh, that's the exit code of killall
$ killall -9 myScript
$ echo $?
0  # same problem

Akzeptierte Antwort:

Prozesse können _exit() aufrufen Systemaufruf (unter Linux siehe auch exit_group()). ) mit einem ganzzahligen Argument, um einen Beendigungscode an ihr übergeordnetes Element zu melden. Obwohl es sich um eine Ganzzahl handelt, stehen dem übergeordneten Element nur die 8 niederwertigsten Bits zur Verfügung (Ausnahme hiervon ist die Verwendung von waitid()). oder Handler auf SIGCHLD im Elternteil, um diesen Code abzurufen, jedoch nicht unter Linux).

Der Elternteil führt normalerweise ein wait() aus oder waitpid() um den Status zu erhalten ihres Kindes als Ganzzahl (obwohl waitid() mit etwas anderer Semantik können ebenfalls verwendet werden).

Unter Linux und den meisten Unices, wenn der Prozess normal beendet wurde, die Bits 8 bis 15 dieses Status Zahl enthält den Exit-Code, wie er an exit() übergeben wird . Wenn nicht, enthalten die 7 niederwertigsten Bits (0 bis 6) die Signalnummer und Bit 7 wird gesetzt, wenn ein Kern ausgegeben wurde.

perl ist $? enthält beispielsweise diese Zahl, wie sie von waitpid() gesetzt wird :

$ perl -e 'system q(kill $$); printf "%04xn", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04xn", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04xn", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status

Bourne-ähnliche Shells machen auch den Exit-Status des letzten Ausführungsbefehls in ihrem eigenen $? Variable. Sie enthält jedoch nicht direkt die von waitpid() zurückgegebene Zahl , aber eine Transformation darauf, und es ist zwischen den Shells unterschiedlich.

Was alle Shells gemeinsam haben, ist das $? enthält die niedrigsten 8 Bits des Exit-Codes (die Zahl, die an exit() übergeben wird ), wenn der Prozess normal beendet wurde.

Wo es sich unterscheidet, ist, wenn der Prozess durch ein Signal beendet wird. In allen Fällen, und das wird von POSIX verlangt, ist die Zahl größer als 128. POSIX gibt nicht an, was der Wert sein kann. In der Praxis sind jedoch in allen Bourne-ähnlichen Shells, die ich kenne, die niedrigsten 7 Bits von $? enthält die Signalnummer. Aber wo n ist die Signalnummer,

  • in ash, zsh, pdksh, bash, der Bourne-Shell, $? ist 128 + n . Das bedeutet, dass in diesen Shells ein $? angezeigt wird von 129 , wissen Sie nicht, ob es daran liegt, dass der Prozess mit exit(129) beendet wurde oder ob es durch das Signal 1 getötet wurde (HUP auf den meisten Systemen). Der Grund dafür ist jedoch, dass Shells, wenn sie sich selbst beenden, standardmäßig den Beendigungsstatus des letzten beendeten Befehls zurückgeben. Indem Sie sicherstellen, dass $? ist nie größer als 255, was einen konsistenten Exit-Status ermöglicht:

    $ bash -c 'sh -c "kill $$"; printf "%xn" "$?"'
    bash: line 1: 16720 Terminated              sh -c "kill $$"
    8f # 128 + 15
    $ bash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?"
    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 ab einem Wert von $? Sie können zwischen einem beendeten und einem nicht beendeten Prozess unterscheiden. Neuere Versionen von ksh , beim Beenden, wenn $? größer als 255 war, beendet sich mit dem gleichen Signal selbst, um den gleichen Exit-Status an seinen Parent melden zu können. Das klingt zwar nach einer guten Idee, aber das bedeutet, dass ksh erzeugt einen zusätzlichen Core-Dump (der möglicherweise den anderen überschreibt), wenn der Prozess durch ein Core-Erzeugungssignal beendet wurde:

    $ ksh -c 'sh -c "kill $$"; printf "%xn" "$?"'
    ksh: 16828: Terminated
    10f # 256 + 15
    $ ksh -c 'sh -c "kill -ILL $$"; exit'; printf '%xn' "$?"
    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.
    

    Wo man sogar sagen könnte, dass es einen Fehler gibt, ist dieser ksh93 tötet sich selbst, selbst wenn $? kommt von einem return 257 erfolgt durch eine Funktion:

    $ 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 an. Es gibt 256 + 128 + n zurück . Das bedeutet, dass wir auch zwischen einem beendeten Prozess und einem ordnungsgemäß beendeten Prozess unterscheiden können. Und beim Beenden wird 128 + n gemeldet ohne sich selbst das Leben nehmen zu müssen und die Nebenwirkungen, die es haben kann.

    $ yash -c 'sh -c "kill $$"; printf "%xn" "$?"'
    18f # 256 + 128 + 15
    $ yash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?"
    8f  # that's from a exit(143), yash was not killed
    

Um das Signal aus dem Wert von $? zu erhalten , der portable Weg ist die Verwendung von kill -l :

$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM

(aus Gründen der Portabilität sollten Sie niemals Signalnummern verwenden, sondern nur Signalnamen)

Verwandt:Sicherungen auf Byte- oder Dateiebene?

An den Nicht-Bourne-Fronten:

  • csh /tcsh und fish wie die Bourne-Shell, außer dass der Status in $status steht statt $? (Beachten Sie, dass zsh setzt auch $status für die Kompatibilität mit csh (zusätzlich zu $? )).
  • rc :Der Exit-Status ist in $status auch, aber wenn sie von einem Signal getötet wird, enthält diese Variable den Namen des Signals (wie sigterm oder sigill+core wenn ein Kern generiert wurde) anstelle einer Zahl, was ein weiterer Beweis für das gute Design dieser Hülle ist.
  • es . der Exit-Status ist keine Variable. Wenn es Ihnen wichtig ist, führen Sie den Befehl wie folgt aus:

    status = <={cmd}
    

    was eine Zahl oder sigterm zurückgibt oder sigsegv+core wie in rc .

Vielleicht sollten wir der Vollständigkeit halber zsh erwähnen 's $pipestatus und bash 's $PIPESTATUS Arrays, die den Exit-Status der Komponenten der letzten Pipeline enthalten.

Und auch der Vollständigkeit halber, wenn es um Shell-Funktionen und Quelldateien geht, kehren Funktionen standardmäßig mit dem Exit-Status der letzten Befehlsausführung zurück, können aber auch explizit mit return einen Rückgabestatus setzen eingebaut. Und hier sehen wir einige Unterschiede:

  • bash und mksh (seit R41 eine offenbar absichtlich eingeführte Regression^Wchange) kürzt die Zahl (positiv oder negativ) auf 8 Bit. Also zum Beispiel return 1234 setzt $? bis 210 , return -- -1 setzt $? bis 255.
  • zsh und pdksh (und andere Ableitungen als mksh ) jede vorzeichenbehaftete 32-Bit-Dezimalzahl (-2 bis 2-1) zulassen (und die Zahl auf 32 Bit kürzen).
  • ash und yash erlaubt jede positive ganze Zahl von 0 bis 2-1 und gibt einen Fehler für jede Zahl davon zurück.
  • ksh93 für return 0 um return 320 setze $? unverändert, aber für alles andere auf 8 Bit abschneiden. Beachten Sie, wie bereits erwähnt, dass die Rückgabe einer Zahl zwischen 256 und 320 zu ksh führen kann um sich beim Beenden selbst zu töten.
  • rc und es alles zurückgeben lassen, sogar Listen.
Verwandte:arduino – Benötigt gcode einen Antwortcode vom Interpreter?

Beachten Sie auch, dass einige Shells auch spezielle Werte von $? verwenden /$status um einige Fehlerbedingungen zu melden, die nicht der Exit-Status eines Prozesses sind, wie 127 oder 126 für Befehl nicht gefunden oder nicht ausführbar (oder Syntaxfehler in einer Quelldatei)…


Linux
  1. Bash-Befehlszeilen-Exit-Codes entmystifiziert

  2. Linux – Wann sollte ich keinen -9 A-Prozess beenden?

  3. Neuer übergeordneter Prozess, wenn der übergeordnete Prozess stirbt?

  4. Wann wurde "Relatime" zum Standard gemacht?

  5. Welchen Fehlercode gibt ein Prozess zurück, der Segfaults zurückgibt?

Kann exit() den Prozess nicht beenden?

Bash-Eingabeaufforderung mit letztem Exit-Code

Was passiert, wenn sich ein Thread verzweigt?

Linux-Grep-Rückgabecode

Ist es möglich, einen bestimmten Exit-Code zu erzwingen, wenn kill verwendet wird, um einen Prozess zu stoppen?

Wann sollte ich einen Prozess nicht beenden -9?