HOWTO zum Exit-Status von Kommandos =================================== (C) 2006-2026 T.Birnthaler/H.Gottschalk OSTC Open Source Training and Consulting GmbH http://www.ostc.de $Id: shell-exit-code-HOWTO.txt,v 1.11 2026/06/09 17:19:15 tsbirn Exp $ Dieses Dokument beschreibt die Bedeutung des Shell-Exit-Status und seine Nutzung in Shell-Skripten, um den Ablauf in Abhängigkeit vom Ergebnis eines Kommandos zu steuern. ________________________________________________________________________________ Jedes Kommando (jeder Prozess) gibt am Ende einen "Exit-Status" (kleiner Wert im Bereich 0-255) zurück, über den es seinem Elternprozeß mitteilt, ob es korrekt ablief oder ob ein Fehler auftrat. +------------+--------------------------------------------------------+ | Code | Bedeutung | +------------+--------------------------------------------------------+ | 0 | Kommando lief korrekt ab | | ungleich 0 | Bei der Ausführung des Kommandos trat ein FEHLER auf | | | (Wert kann die FEHLERART beschreiben, muss aber nicht) | +------------+--------------------------------------------------------+ HINWEIS: Die Bedeutung der einzelnen Exit-Fehlercodes ist von Kommando zu Kommando VERSCHIEDEN und kann in der jeweiligen man-Page nachgelesen werden (nach dem Begriff "exit status" suchen, er wird oft erst am Ende erläutert). Der Exit-Status kann NUR DIREKT NACH einem Kommando abgefragt und über das Kommando "test" für Verzweigungen des Programmflusses benutzt werden. Er steht auch in der Shell-Variablen "$?" (bzw. "$status" bei der (t)csh) und kann darüber ausgegeben werden. Beispiele: grep TEXT FILE # 0 falls TEXT (Muster) in FILE gefunden # 1 falls TEXT (Muster) in FILE nicht gefunden # 2 falls FILE nicht vorhanden oder TEXT (Muster) fehlerhaft echo $? # Exit-Status ausgeben (nur 1x sinnvoll, da "echo" auch Kmdo.) echo $? # Exit-Status von vorherigem "echo" (Wert "0" da erfolgreich) grep TEXT FILE # 0 falls TEXT (Muster) in FILE gefunden ES=$? # Exit-Status in Variable ES speichern (für mehrfachen Vgl.) Da für die Shell der Wert 0 "logisch wahr" bedeutet und alle anderen Werte 1, 2, ... für sie "logisch falsch" bedeuten, kann über den Exit-Status eines Tests per "[...]" oder "test" der Ablauf eines Shell-Skriptes gesteuert werden: [ -f /tmp/text ] && echo "Datei '/tmp/text' existiert" [ -d /tmp/dir ] || echo "Verzeichnis '/tmp/dir' existiert nicht" Da jedes Kommando/Programm/Skript einen Exit-Status erzeugt, kann sein Erfolg anschließend sofort überprüft und entsprechend reagiert werden (die Fehlermeldungen per "echo" wird dabei auf "stderr" (1>&2) ausgegeben): grep "error:" /tmp/log > /dev/null && echo "Fehler in Log gefunden" 1>&2 mv text /tmp || echo "Datei 'text' nicht verschiebbar" 1>&2 chmod a+w log || echo "Rechte von Datei 'log' nicht änderbar" 1>&2 if grep "error:" /tmp/log > /dev/null then echo "$(grep -c "error:" /tmp/log > /dev/null) Fehler in Log gefunden" else echo "Alles in Ordnung" fi Meist interessiert in einem Shell-Skript die Ausgabe eines Kommandos überhaupt nicht, sondern nur der Exit-Status. D.h. beim Kommando-Aufruf wirft man alle Ausgaben per Umleitung mit einer der folgenden drei Möglichkeiten weg: if grep "error:" /tmp/log > /dev/null 2> /dev/null; ... if grep "error:" /tmp/log > /dev/null 1>&2; ... if grep "error:" /tmp/log >& /dev/null; ... Die Shell (bash, ksh) selbst kennt zwei Exit-Status mit denen sie den fehlgeschlagenen Aufruf eines Kommandos kommuniziert: +-------------+-------------------------------------------------+ | Exit-Status | Bedeutung | +-------------+-------------------------------------------------+ | 126 | Kommando gefunden, aber nicht lesbar/ausführbar | | 127 | Kommando nicht gefunden | +-------------+-------------------------------------------------+ Beim Abbruch eines Kommandos per SIGNAL wird die Signal-Nummer + 128 als Exit-Status zurückgegeben: +----------------+------------+---------+---------------+ | ES = 128 + Sig | Bedeutung | Name | Steuerzeichen | +----------------+------------+---------+---------------+ | 129 = 128 + 1 | Hangup | SIGHUP | Strg-D | | 130 = 128 + 2 | Interrrupt | SIGINT | Strg-C | | 131 = 128 + 3 | Quit | SIGQUIT | | | 134 = 128 + 6 | Abort | SIGABRT | | | 137 = 128 + 9 | Kill | SIGKILL | | | 138 = 128 + 10 | User 1 | SIGUSR1 | | | 140 = 128 + 12 | User 2 | SIGUSR2 | | | 141 = 128 + 13 | Pipe | SIGPIPE | | | 142 = 128 + 14 | Alarm | SIGALRM | | | 143 = 128 + 15 | Terminate | SIGTERM | | | 145 = 128 + 17 | Child | SIGCHLD | | | 146 = 128 + 18 | Continue | SIGCONT | Strg-Q | | 147 = 128 + 19 | Stop | SIGSTOP | Strg-S | | 148 = 128 + 20 | Typed Stop | SIGTSTP | Strg-Z | +----------------+------------+---------+---------------+