Gibt es unter Linux Standard-Exit-Statuscodes?

308

Ein Prozess wird unter Linux als korrekt abgeschlossen angesehen, wenn sein Exit-Status 0 war.

Ich habe gesehen, dass Segmentierungsfehler häufig zu einem Exit-Status von 11 führen, obwohl ich nicht weiß, ob dies einfach die Konvention ist, bei der ich arbeite (die Apps, die so fehlgeschlagen sind, waren alle intern) oder ein Standard.

Gibt es Standard-Exit-Codes für Prozesse unter Linux?

Nathan Fellman
quelle
6
Wenn Sie nach dem Ding suchen, das "Systemfehlernummer" genannt wird und von Systemfunktionen zurückgegeben wird, schauen Sie hier bei errno
marinara

Antworten:

86

8 Bits des Rückkehrcodes und 8 Bits der Nummer des Tötungssignals werden bei der Rückkehr von wait(2)& co zu einem einzigen Wert gemischt . .

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

int main() {
    int status;

    pid_t child = fork();
    if (child <= 0)
        exit(42);
    waitpid(child, &status, 0);
    if (WIFEXITED(status))
        printf("first child exited with %u\n", WEXITSTATUS(status));
    /* prints: "first child exited with 42" */

    child = fork();
    if (child <= 0)
        kill(getpid(), SIGSEGV);
    waitpid(child, &status, 0);
    if (WIFSIGNALED(status))
        printf("second child died with %u\n", WTERMSIG(status));
    /* prints: "second child died with 11" */
}

Wie bestimmen Sie den Exit-Status? Traditionell speichert die Shell nur einen 8-Bit-Rückkehrcode, setzt jedoch das High-Bit, wenn der Prozess abnormal beendet wurde.

$ sh -c 'Ausfahrt 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Segmentierungsfehler
139
$ expr 139 - 128
11

Wenn Sie etwas anderes sehen, verfügt das Programm wahrscheinlich über einen SIGSEGVSignalhandler, der dann exitnormal aufruft , sodass es nicht durch das Signal getötet wird. (Programme können alle Signale außer SIGKILLund verarbeiten SIGSTOP.)

kurzlebig
quelle
8
Angesichts der Art und Weise, wie die Frage jetzt angezeigt wird, scheint dies nicht die nützlichste (und damit akzeptierte) Antwort zu sein.
David J.
332

Teil 1: Advanced Bash Scripting Guide

Wie immer die erweiterte Bash Scripting Guide hat große Informationen : (. Dies wurde in einer anderen Antwort verknüpft ist , sondern auf eine nicht-kanonische URL)

1: Catchall für allgemeine Fehler
2: Missbrauch von Shell-Buildins (gemäß Bash-Dokumentation)
126: Der aufgerufene Befehl kann nicht ausgeführt werden
127: "Befehl nicht gefunden"
128: Ungültiges Argument zum Beenden
128 + n: Schwerwiegendes Fehlersignal "n"
255: Beenden Status außerhalb des Bereichs (Exit akzeptiert nur ganzzahlige Argumente im Bereich von 0 bis 255)

Teil 2: sysexits.h

Die ABSG-Referenzen sysexits.h.

Unter Linux:

$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h

/*
 * Copyright (c) 1987, 1993
 *  The Regents of the University of California.  All rights reserved.

 (A whole bunch of text left out.)

#define EX_OK           0       /* successful termination */
#define EX__BASE        64      /* base value for error messages */
#define EX_USAGE        64      /* command line usage error */
#define EX_DATAERR      65      /* data format error */
#define EX_NOINPUT      66      /* cannot open input */    
#define EX_NOUSER       67      /* addressee unknown */    
#define EX_NOHOST       68      /* host name unknown */
#define EX_UNAVAILABLE  69      /* service unavailable */
#define EX_SOFTWARE     70      /* internal software error */
#define EX_OSERR        71      /* system error (e.g., can't fork) */
#define EX_OSFILE       72      /* critical OS file missing */
#define EX_CANTCREAT    73      /* can't create (user) output file */
#define EX_IOERR        74      /* input/output error */
#define EX_TEMPFAIL     75      /* temp failure; user is invited to retry */
#define EX_PROTOCOL     76      /* remote error in protocol */
#define EX_NOPERM       77      /* permission denied */
#define EX_CONFIG       78      /* configuration error */

#define EX__MAX 78      /* maximum listed value */
Schof
quelle
5
Beachten Sie, dass in einigen Unix-Varianten einige Befehle den Exit-Status 2 verwenden, um andere Dinge anzuzeigen. Beispielsweise verwenden viele Implementierungen von grep einen Exit-Status von 2, um einen Fehler anzuzeigen, und einen Exit-Status von 1, um zu bedeuten, dass keine ausgewählten Zeilen gefunden wurden.
NamshubWriter
3
Auf BSDs gibt es eine Manpage, die die Informationen von sysexits.h zusammenfasst:man sysexits
georgebrock
6
Was @NamshubWriter gesagt hat. Der Exit-Status 2 ist die universelle Anlaufstelle für die falsche Verwendung der Befehlszeile in Unix-Dienstprogrammen, nicht nur in "einigen Unix-Varianten", sondern im Allgemeinen. Der in dieser Antwort gezeigte Header spiegelt nicht die tatsächlichen Konventionen wider, weder jetzt noch als er 1987 geschrieben wurde.
Alexis
Das ABS ist nicht "toll". Bitte lesen Sie das Thema; Kritik ist nicht gerade schwer zu finden.
Tripleee
Aber wo ist der eigentliche offizielle Quellcode sysexits.h? Die Manpage, auf die sich jeder bezieht, ist nur Prosa. Zum Beispiel verweist es darauf EX_OK, definiert es aber nicht normativ wie die anderen Codes. Fehlen noch mehr?
Garret Wilson
71

'1' >>> Catchall für allgemeine Fehler

'2' >>> Missbrauch von Shell-Builtins (laut Bash-Dokumentation)

'126' >>> Der aufgerufene Befehl kann nicht ausgeführt werden

'127' >>> "Befehl nicht gefunden"

'128' >>> Ungültiges Argument zum Beenden

'128 + n' >>> Schwerwiegendes Fehlersignal "n"

'130' >>> Skript von Control-C beendet

'255' >>> Status außerhalb des Bereichs verlassen

Dies ist für Bash. Für andere Anwendungen gibt es jedoch andere Exit-Codes.

Segfault
quelle
1
Es sieht so aus, als hätten Sie beide in derselben Minute geantwortet. Tian müsste ziemlich schnell sein, um Ihre Links zu sehen und sie
einzufügen
6
Es ist zu beachten, dass 'Kontrolle-C ergibt 130' mit '128 + n' für Signal n übereinstimmt; Kontrolle-C erzeugt SIGINT, das Signal 2 ist.
Jonathan Leffler
3
Dies scheint vom ABS ohne Zuschreibung plagiiert zu werden. (Wir können sagen, weil das ABS falsche oder zumindest irreführende Informationen enthält.)
Tripleee
4
Dies sind RESERVIERTE Exit-Codes gemäß dem Advanced Bash-Scripting Guide . Das heißt, diese Werte sollten daher für benutzerdefinierte Exit-Parameter vermieden werden .
Ingyhere
53

Keine der älteren Antworten beschreibt den Exit-Status 2 korrekt. Im Gegensatz zu dem, was sie behaupten, geben Status 2 Ihre Befehlszeilen-Dienstprogramme tatsächlich zurück, wenn sie nicht ordnungsgemäß aufgerufen werden. (Ja, eine Antwort kann neun Jahre alt sein, Hunderte von positiven Stimmen haben und immer noch falsch sein.)

Hier ist die reale, langjährige Exit-Status-Konvention für die normale Beendigung, dh nicht per Signal:

  • Exit Status 0: Erfolg
  • Beenden Sie Status 1: "Fehler", wie vom Programm definiert
  • Beenden Sie Status 2: Befehlszeilenverwendungsfehler

Gibt beispielsweise diff0 zurück, wenn die verglichenen Dateien identisch sind, und 1, wenn sie sich unterscheiden. Durch die langjährige Konvention zurückkehren Unix - Programme Exit - Status 2 , wenn falsch genannt (unbekannte Optionen, falsche Anzahl von Argumenten, etc.) zum Beispiel diff -N, grep -Yoder diff a b cwird alle Ergebnisse in $?seinem Set 2. die Praxis ist dies und ist seit der Anfänge von Unix in den 1970er Jahren.

Die akzeptierte Antwort erklärt, was passiert, wenn ein Befehl durch ein Signal beendet wird. Kurz gesagt, eine Beendigung aufgrund eines nicht erfassten Signals führt zum Exit-Status 128+[<signal number>. Beispielsweise führt die Beendigung durch SIGINT( Signal 2 ) zum Ausgangsstatus 130.

Anmerkungen

  1. Mehrere Antworten definieren den Exit-Status 2 als "Missbrauch von Bash-Buildins". Dies gilt nur, wenn bash (oder ein bash-Skript) mit Status 2 beendet wird. Betrachten Sie dies als einen Sonderfall eines falschen Verwendungsfehlers.

  2. In sysexits.h, wie in der beliebtesten Antwort erwähnt , wird der Exit-Status EX_USAGE("Befehlszeilen-Verwendungsfehler") als 64 definiert. Dies spiegelt jedoch nicht die Realität wider: Mir ist kein allgemeines Unix-Dienstprogramm bekannt, das bei falschem Aufruf 64 zurückgibt (Beispiele willkommen ). Das sorgfältige Lesen des Quellcodes zeigt, dass dies sysexits.heher ein Ziel als ein Spiegelbild der tatsächlichen Verwendung ist:

     *    This include file attempts to categorize possible error
     *    exit statuses for system programs, notably delivermail
     *    and the Berkeley network.
    
     *    Error numbers begin at EX__BASE [64] to reduce the possibility of 
     *    clashing with oth­er exit statuses that random programs may 
     *    already return. 
    

    Mit anderen Worten, diese Definitionen spiegeln nicht die damals übliche Praxis (1993) wider, waren jedoch absichtlich nicht damit vereinbar. Mehr ist schade.

alexis
quelle
Was sollte ein Programm zurückgeben, wenn es die Beendigung durch Abfangen von SIGINT / Strg-C behandelt? Immer noch 130? Ist die Verwendung einer anderen Shell als Bash wichtig?
Gringo Suave
1
Die Shell, die das Programm ausführt, ist irrelevant. Ein Prozess könnte theoretisch abhängig von seinem übergeordneten Prozess mit einem anderen Status beendet werden, aber ich habe noch nie von einem Fall gehört, in dem dies geschieht.
Alexis
1
Wenn ein Programm SIGINT abfängt, bereinigt und trotzdem beendet, ist der Status das, was für das Programm sinnvoll ist. Zum Beispiel morewerden die Terminalmodi zurückgesetzt und mit dem Status 0 beendet (Sie können es versuchen).
Alexis
1
Diese Antwort impliziert einen viel höheren Standardisierungsgrad als dies tatsächlich der Fall ist. Es gibt keine ordnungsgemäße Standardisierung der Bedeutung des Werts 2, und die tatsächliche Praxis ist dann vorhersehbar sehr gemischt. Es ist richtig, dass viele Tools 2 für eine missbräuchliche Verwendung zurückgeben, aber es ist nicht genau definiert, was "unsachgemäße Verwendung" bedeutet, und viele andere halten sich nicht an diese Konvention.
Tripleee
@tripleee "tools" ist auch nicht gut definiert! :-) Sicher, jeder kann ein Befehlszeilenprogramm schreiben und es kann überhaupt alles zurückgeben, aber die alten "Unix-Befehlszeilenprogramme", die es schon länger als Linux gibt, oder der Inhalt von GNU-Coreutils sind recht konsequent darauf. Wenn Sie anders denken, nennen Sie bitte einige Tools in dieser Gruppe, die Status 2 nicht auf diese Weise verwenden. Auch "missbräuchliche Verwendung" ist Ihr Begriff (und ich stimme zu, dass es ein vager Begriff ist); Ich habe einen "Befehlszeilen-Verwendungsfehler" geschrieben, der ziemlich spezifisch ist: nicht vorhandene oder inkompatible Optionen, falsche Anzahl von Nicht-Options-Argumenten usw.
alexis
25

Abgesehen von 0, was Erfolg bedeutet, gibt es keine Standard-Exit-Codes. Ein Wert ungleich Null bedeutet auch nicht unbedingt einen Fehler.

stdlib.h definiert EXIT_FAILUREals 1 und EXIT_SUCCESSals 0, aber das war es auch schon.

Die 11 bei Segfault ist interessant, da 11 die Signalnummer ist, die der Kernel verwendet, um den Prozess im Falle eines Segfault zu beenden. Es gibt wahrscheinlich einen Mechanismus, entweder im Kernel oder in der Shell, der dies in den Exit-Code übersetzt.

Chris Arguin
quelle
20

sysexits.h enthält eine Liste der Standard-Exit-Codes. Es scheint mindestens aus dem Jahr 1993 zu stammen und wird von einigen großen Projekten wie Postfix verwendet. Ich kann mir also vorstellen, dass dies der richtige Weg ist.

Von der OpenBSD-Manpage:

Gemäß Stil (9) ist es nicht empfehlenswert, exit (3) mit willkürlichen Werten aufzurufen, um einen Fehlerzustand beim Beenden eines Programms anzuzeigen. Stattdessen sollten die vordefinierten Exit-Codes von Sysexits verwendet werden, damit der Aufrufer des Prozesses eine grobe Schätzung der Fehlerklasse erhalten kann, ohne den Quellcode nachzuschlagen.

quelle
8

In erster Näherung ist 0 Erfolg, Nicht-Null ist Fehler, wobei 1 allgemeiner Fehler ist und alles, was größer als eins ist, ein spezifischer Fehler ist. Abgesehen von den trivialen Ausnahmen von false und test, die beide 1 für den Erfolg ergeben sollen, habe ich noch einige andere Ausnahmen gefunden.

Realistischer bedeutet 0 Erfolg oder vielleicht Misserfolg, 1 bedeutet allgemeiner Misserfolg oder vielleicht Erfolg, 2 bedeutet allgemeiner Misserfolg, wenn 1 und 0 beide für Erfolg verwendet werden, aber vielleicht auch Erfolg.

Der Befehl diff gibt 0 an, wenn die verglichenen Dateien identisch sind, 1, wenn sie sich unterscheiden, und 2, wenn sich die Binärdateien unterscheiden. 2 bedeutet auch Fehler. Der Befehl less gibt 1 für Fehler an, es sei denn, Sie geben kein Argument an. In diesem Fall wird 0 trotz Fehler beendet.

Der Befehl more und der Befehl buchstabieren geben 1 für Fehler an, es sei denn, der Fehler ist auf eine verweigerte Berechtigung, eine nicht vorhandene Datei oder den Versuch zurückzuführen, ein Verzeichnis zu lesen. In jedem dieser Fälle beenden sie 0, obwohl sie fehlschlagen.

Dann gibt der Befehl expr 1 für sucess aus, es sei denn, die Ausgabe ist die leere Zeichenfolge oder Null. In diesem Fall ist 0 sucess. 2 und 3 sind Fehler.

Dann gibt es Fälle, in denen Erfolg oder Misserfolg nicht eindeutig sind. Wenn grep kein Muster findet, wird 1 beendet, 2 jedoch für einen echten Fehler (wie die verweigerte Berechtigung). Klist beendet 1 auch, wenn es kein Ticket findet, obwohl dies nicht wirklich ein Fehler ist, als wenn grep kein Muster findet oder wenn Sie ein leeres Verzeichnis haben.

Leider scheinen die vorhandenen Unix-Kräfte keine logischen Regeln durchzusetzen, selbst bei sehr häufig verwendeten ausführbaren Dateien.

Friedrich
quelle
Ich wollte auch auf das Verhalten von diff hinweisen. wget hat auch detaillierte Fehler (zB 6 für Authentifizierungsfehler), aber dann verwenden sie 1 = generischer Fehler, 2..n = spezifischer Fehler
PypeBros
5

Programme geben einen 16-Bit-Exit-Code zurück. Wenn das Programm mit einem Signal beendet wurde, enthält das Byte höherer Ordnung das verwendete Signal, andernfalls ist das Byte niedriger Ordnung der vom Programmierer zurückgegebene Exit-Status.

Wie wird dieser Exit-Code der Statusvariablen $ zugewiesen? liegt dann an der Shell. Bash behält die unteren 7 Bits des Status bei und verwendet dann 128 + (Signal nr) zur Anzeige eines Signals.

Die einzige "Standard" -Konvention für Programme ist 0 für Erfolg, ungleich Null für Fehler. Eine andere verwendete Konvention ist die Rückgabe von errno bei einem Fehler.

Dean Povey
quelle
3

Standard-Unix-Exit-Codes werden von sysexits.h als weiteres erwähntes Poster definiert. Dieselben Exit-Codes werden von tragbaren Bibliotheken wie Poco verwendet - hier eine Liste davon:

http://pocoproject.org/docs/Poco.Util.Application.html#16218

Ein Signal 11 ist ein SIGSEGV-Signal (Segmentverletzung), das sich von einem Rückkehrcode unterscheidet. Dieses Signal wird vom Kernel als Reaktion auf einen fehlerhaften Seitenzugriff generiert, wodurch das Programm beendet wird. Eine Liste der Signale finden Sie auf der Signal-Manpage (führen Sie "Man-Signal" aus).

Daniel Schuler
quelle
1

Wenn Linux 0 zurückgibt, bedeutet dies Erfolg. Alles andere bedeutet Fehler, jedes Programm hat seine eigenen Exit-Codes, daher wäre es ziemlich lang gewesen, sie alle aufzulisten ...!

Bei dem 11-Fehlercode handelt es sich tatsächlich um die Segmentierungsfehlernummer, was hauptsächlich bedeutet, dass das Programm auf einen Speicherort zugegriffen hat, der nicht zugewiesen wurde.

Amadeus45
quelle
1
Es ist immer 11, weil der Kernel es beendet und den "Exit-Wert" zuweist. Ebenso erhalten andere Arten von Fehlern immer den gleichen Ausgangswert.
Alex Gartrell