Ich bin kürzlich auf diese Liste von Exit-Codes mit besonderer Bedeutung aus dem Advanced Bash-Scripting Guide gestoßen. Sie bezeichnen diese Codes als reserviert und empfehlen Folgendes:
Gemäß der obigen Tabelle haben die Exit-Codes 1-2, 126-165 und 255 eine spezielle Bedeutung und sollten daher für benutzerdefinierte Exit-Parameter vermieden werden.
Vor einiger Zeit habe ich ein Skript geschrieben, das die folgenden Beendigungsstatuscodes verwendet:
- 0 - Erfolg
- 1 - falscher Hostname
- 2 - ungültige Argumente angegeben
- 3 - unzureichende Benutzerrechte
Als ich das Skript schrieb, waren mir keine speziellen Exit-Codes bekannt, und ich begann einfach bei 1 für die erste Fehlerbedingung und erhöhte den Exit-Status für jeden nachfolgenden Fehlertyp.
Ich habe das Skript mit der Absicht geschrieben, dass es zu einem späteren Zeitpunkt von anderen Skripten aufgerufen werden kann (die nach Exit-Codes ungleich Null suchen können). Das habe ich noch nicht gemacht. Bisher habe ich das Skript nur über meine interaktive Shell (Bash) ausgeführt und mich gefragt, was bzw. ob Probleme durch die Verwendung meiner benutzerdefinierten Beendigungscodes verursacht werden könnten. Wie relevant / wichtig ist die Empfehlung aus dem Advanced Bash-Scripting Guide?
Ich konnte keine bestätigenden Hinweise in der Bash-Dokumentation finden. Der Abschnitt über den Beendigungsstatus listet lediglich die von Bash verwendeten Beendigungscodes auf, gibt jedoch nicht an, dass diese reserviert sind , oder warnt vor deren Verwendung für Ihre eigenen Skripte / Programme.
quelle
Antworten:
Es wurden mehrere Versuche unternommen, die Bedeutung von Prozess-Exit-Codes zu standardisieren. Zusätzlich zu dem, den Sie erwähnen, weiß ich von:
Die BSDs haben
sysexits.h
Bedeutungen für Werte ab 64.GNU-
grep
Dokumente, deren Beendigungscode 0 bedeutet, dass mindestens eine Übereinstimmung gefunden wurde, 1 bedeutet, dass keine Übereinstimmung gefunden wurde, und 2 bedeutet, dass ein E / A-Fehler aufgetreten ist; Diese Konvention ist natürlich auch für andere Programme nützlich, bei denen die Unterscheidung zwischen "nichts ist schiefgegangen, aber ich habe nichts gefunden" und "ein E / A-Fehler ist aufgetreten" sinnvoll ist.Viele Implementierungen der C-Bibliotheksfunktion
system
verwenden den Exit-Code 127, um anzuzeigen, dass das Programm nicht vorhanden ist oder nicht gestartet werden konnte.Unter Windows können
NTSTATUS
Codes (die ungünstigerweise über den gesamten 32-Bit-Nummernraum verteilt sind) als Exit-Codes verwendet werden, insbesondere solche, die darauf hinweisen, dass ein Prozess aufgrund eines katastrophalen Fehlverhaltens abgebrochen wurde (zSTATUS_STACK_OVERFLOW
. B. ).Sie können sich nicht darauf verlassen, dass ein bestimmtes Programm eine dieser Konventionen einhält. Die einzig verlässliche Regel ist, dass der Exit-Code 0 erfolgreich ist und alles andere ein Fehler ist. (Beachten Sie, dass C89 der
EXIT_SUCCESS
wird nicht garantiert den Wert Null haben, aberexit(0)
ist erforderlich , identisch zu verhaltenexit(EXIT_SUCCESS)
. Auch wenn die Werte nicht gleich sind )quelle
Kein Exit-Code hat eine besondere Bedeutung, aber der Wert in
$?
kann eine besondere Bedeutung haben.Die Art und Weise, wie Bourne Shell und ksh93 Exit-Codes und Fehlersituationen an die Shell-Variable handhabten und weiterleiteten,
$?
ist das Problem. Im Gegensatz zu Ihrer Auflistung haben nur die folgenden Werte für$?
eine besondere Bedeutung:Zusätzlich gibt es einen nicht spezifizierten shell- und plattformspezifischen
$?
Codebereich> 128, der für ein Programm reserviert ist, das durch ein Signal unterbrochen wurde:Andere Werte geben keine Probleme, da sie von den Shell-Spezialwerten unterschieden werden
$?
können.Insbesondere werden die Werte 1 und 2 nicht für spezielle Bedingungen verwendet, sondern sind lediglich Exit-Codes, die von integrierten Befehlen verwendet werden, die dasselbe Verhalten zeigen können, wenn sie keine integrierten Befehle sind. Es scheint also, dass der Zeiger auf die von Ihnen bereitgestellte Bash-Skriptanleitung kein gutes Handbuch ist, da er nur die von Bash verwendeten Codes auflistet, ohne zu kommentieren, ob ein bestimmter Code ein besonderer Wert ist, der für eigene Skripte vermieden werden sollte.
Neuere Versionen der Bourne - Shell verwenden ,
waitid()
stattwaitpid()
für das Programm zu beenden , zu warten undwaitid()
(1989 für SVr4 eingeführt) verwendet eine bessere syscall - Schnittstelle (ähnlich dem , was UNOS bereits im Jahr 1980 verwendet).Da neuere Bourne Shell-Versionen den Exit-Grund in einer separaten Variablen
${.sh.code}
/${.sh.codename}
als den Exit-Code in${.sh.status}
/ codieren${.sh.termsig}
(siehe http://schillix.sourceforge.net/man/man1/bosh.1.html) , wird der Exit-Code nicht überladen mit speziellen Zuständen und als Ergebnis der Verwendung von `waitid () unterstützt die Bourne-Shell jetzt die Rückgabe aller 32 Bits des Exit-Codes - nicht nur der niedrigen 8 Bits.Übrigens: Achten Sie darauf, dass Sie kein
exit(256)
C-Programm oder Shell-Skript verwenden, da dies dazu führt,$?
dass es in einer klassischen Shell als 0 interpretiert wird.quelle
waitid()
Ende Mai einen Fehlerbericht gegen FreeBSD und den Linux-Kernel für diesen Fehler erstellt. Die FreeBSD-Leute haben das Problem innerhalb von 20 Stunden behoben, die Linux-Leute sind nicht daran interessiert, ihren Fehler zu beheben. ... und die Cygwin-Leute sagen, dass sie Bug-by-Bug-Linux-kompatibel sind ;-)_exit
. Bitte verlinken Sie den FreeBSD-Fehlerbericht, auf den Sie sich beziehen. Vielleicht verstehe ich das von Ihnen beschriebene Problem falsch.${.sh.}
Variablen werden nicht unterstützt . Es ist jedoch richtig, dass Sie "Bourne" und nicht "von Bourne abgeleitet" sagen (obwohl Sie ksh93 einschließen)./bin/sh
kann sich darauf verlassen, dass sich diese speziellen Exit-Codes plattformübergreifend konsistent verhalten, was jedoch nicht zutrifft. (Es ist mir egal, ob ein bestimmtes System/bin/sh
als "echte Bourne-Shell" bezeichnet werden kann. Viel wichtiger ist zu wissen, dass nichts davon in POSIX vorkommt und dass die meisten Dinge, die Sie als "echte Unix-Systeme" bezeichnen, nicht funktionieren.)/bin/sh
Für Shell-Skripte habe ich manchmal das Shell-Äquivalent
sysexist.h
mit Shell-reservierten Exit-Codes (mit PräfixS_EX_
), die ich benannt habe , in den Quellcode eingefügtexit.sh
Es ist im Grunde:
Und kann generiert werden mit:
Ich benutze es zwar nicht viel, aber was ich benutze, ist eine Shell-Funktion, die Fehlercodes in ihre Zeichenfolgenformate umkehrt. Ich habe es benannt
exit2str
. Vorausgesetzt, Sie haben den obigenexit.sh
Generator benanntexit.sh.sh
, kann der Code fürexit2str
mit (exit2str.sh.sh
) generiert werden :Ich verwende dies in
PS1
meiner interaktiven Shell, damit ich nach jedem Befehl, den ich ausführe, den Beendigungsstatus und die Zeichenfolgenform sehen kann (falls eine bekannte Zeichenfolgenform vorliegt):Um diese zu bekommen, benötigen Sie ein Insourcable für die exit2str Funktion:
und verwenden Sie es dann in Ihrem
~/.bashrc
, um den Exit-Code an jeder Eingabeaufforderung zu speichern und zu übersetzen und ihn als Eingabeaufforderung anzuzeigen (PS1
):Es ist sehr praktisch, um zu beobachten, wie einige Programme den Exit-Code-Konventionen folgen und andere nicht, um sich mit Exit-Code-Konventionen vertraut zu machen oder einfach nur zu sehen, was leichter vor sich geht. Nachdem ich es einige Zeit benutzt habe, kann ich sagen, dass viele systemorientierte Shell-Skripte den Konventionen folgen.
EX_USAGE
Besonders häufig ist, obwohl andere Codes, nicht viel. Ich versuche von Zeit zu Zeit die Konventionen zu befolgen, obwohl es immer$S_EX_ANY
(1) für faule Leute gibt (ich bin einer).quelle
Solange Sie Ihre Beendigungscodes so dokumentieren, dass Sie sich in einem Jahr daran erinnern, wann Sie zurückkommen und das Skript optimieren müssen, ist alles in Ordnung. Die Idee der "reservierten Exit-Codes" gilt eigentlich nur, um zu sagen, dass es üblich ist, sie
0
als Erfolgscode und alles andere als Fehlercode zu verwenden.quelle
Die beste Referenz, die ich finden konnte, war: http://tldp.org/LDP/abs/html/exitcodes.html
Demzufolge:
1
ist ein allgemeiner Fehlerfang, und ich habe immer gesehen, dass er für benutzerdefinierte Fehler verwendet wird.2
ist für den Missbrauch von Shell-Built-Ins gedacht, z. B. für einen SyntaxfehlerUm Ihre Frage direkt zu beantworten, ist Ihr Skript mit den reservierten Fehlercodes in Ordnung. Es funktioniert wie erwartet, vorausgesetzt, Sie behandeln den Fehler basierend auf dem Fehlercode = 1/2/3.
Es wäre jedoch möglicherweise verwirrend, wenn Sie auf jemanden stoßen, der die reservierten Fehlercodes kennt und verwendet, was ziemlich selten zu sein scheint.
Eine andere Option, die Ihnen zur Verfügung steht, besteht darin, den Fehler zu wiederholen, falls einer vorliegt, und ihn dann zu beenden, vorausgesetzt, Ihr Skript folgt der Linux-Konvention "Keine Nachrichten sind gute Nachrichten", und es wird nichts für den Erfolg ausgegeben.
quelle
Basierend auf den Antworten, die ich erhalten habe (es war schwierig, eine über die anderen zu wählen), ist es nicht schädlich , bestimmte Arten von Fehlern durch die Verwendung eines Exit-Codes anzuzeigen, den Bash auch verwendet. Bash (oder eine andere Unix-Shell) führt keine besonderen Aktionen aus (z. B. das Ausführen von Ausnahmehandlern), wenn ein Benutzerskript mit einem dieser Fehlercodes beendet wird.
Es scheint, dass der Autor des Advanced Bash-Scripting Guide den BSD-Versuchen zur Standardisierung von Exit-Codes (
sysexits.h
) zustimmt und einfach empfiehlt, dass Benutzer beim Schreiben von Shell-Skripten keine Exit-Codes angeben, die bereits mit vordefinierten Exit-Codes in Konflikt stehen im Einsatz, dh, sie beschränken ihre benutzerdefinierten Beendigungscodes auf die 50 verfügbaren Statuscodes im Bereich von 64 bis 113.Ich schätze die Idee (und das Grundprinzip), aber ich hätte es vorgezogen, wenn der Autor expliziter gesagt hätte, dass es nicht schädlich ist, den Rat zu ignorieren - abgesehen von Fällen, in denen der Konsument eines Skripts nach Fehlern sucht, wie im zitierten Beispiel von 127 (
command not found
).Relevante POSIX-Spezifikationen
Ich habe nachgeforscht, was POSIX über Exit-Codes zu sagen hat, und die POSIX-Spezifikation scheint mit dem Autor des Advanced Bash-Scripting Guide übereinzustimmen. Ich habe die relevanten POSIX-Spezifikationen zitiert (Schwerpunkt meine):
Beenden Sie den Status für Befehle
Das
exit
DienstprogrammWeitere Informationen
Für das, was es wert ist, war ich in der Lage, alle bis auf einen der Exit-Codes mit speziellen Bedeutungen zu überprüfen . Diese Tabelle mit Exit-Codes ist nützlich, da sie weitere Details und Beispiele zum Generieren der in der Bash-Referenz dokumentierten Fehlercodes enthält .
Versuchen Sie, den Exit-Status 128 zu generieren
Mit den Bash-Versionen 3.2.25 und 4.2.46 habe ich versucht, einen
128 Invalid argument to exit
Fehler zu werfen , aber jedes Mal, wenn ich eine 255 erhalten habe (Exit-Status außerhalb des gültigen Bereichs). Wirdexit 3.14159
die Shell beispielsweise als Teil eines Shell-Skripts oder in einer interaktiven untergeordneten Shell ausgeführt, wird die Shell mit dem folgenden Code beendet255
:Um noch mehr Spaß zu haben, habe ich auch versucht, ein einfaches C-Programm auszuführen. In diesem Fall hat die
exit(3)
Funktion den float-Wert einfach vor dem Beenden in einen int-Wert (in diesem Fall 3) konvertiert:quelle