Erfassen Sie den Exit-Code des Exit-Befehls

10

Ich habe dies in einem Bash-Skript:

exit 3;

exit_code="$?"

if [[ "$exit_code" != "0" ]]; then
    echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}";
    exit "$exit_code";
fi

Es sieht so aus, als würde es direkt nach dem Befehl exit beendet, was sinnvoll ist. Ich habe mich gefragt, ob es einen einfachen Befehl gibt, der einen Exit-Code bereitstellen kann, ohne sofort zu beenden.

Ich wollte raten:

exec exit 3

aber es gibt eine Fehlermeldung : exec: exit: not found. Was kann ich tun? :) :)

G-Man sagt "Reinstate Monica"
quelle
1
Ja exec exit 3ist kein bueno, ich bekomme"exec: exit: not found"
7
Ich verstehe die Frage nicht. Warum nicht exit_code=3die exit 3Linie ganz setzen und eliminieren ?
Wjandrea
@wjandrea ist eher eine konzeptionelle als eine praktische Frage
2
Es macht für mich immer noch keinen Sinn. Warum sollte es einen Exit-Code geben, wenn Sie nicht tatsächlich beenden?
Barmar
1
@Barmar Jeder Prozess hat einen Exit-Code. Die meisten Leute, die versuchen, die Frage zu beantworten, interpretieren die Frage so, dass sie bedeutet: "Was kann ich im Skript durch" Exit 3 "ersetzen, damit die $?Variable festgelegt wird, dieses Skript jedoch nicht beendet wird ?"
icarus

Antworten:

32

Wenn Sie ein Skript haben, das ein Programm ausführt und den Exit-Status des Programms (mit  $?) überprüft, und Sie dieses Skript testen möchten, indem Sie etwas tun , das dazu führt $?, dass ein bekannter Wert festgelegt wird (z. B.  3), tun Sie dies einfach

(exit 3)

Die Klammern erstellen eine Unterschale. Dann exitbewirkt der Befehl, dass diese Sub-Shell mit dem angegebenen Exit-Status beendet wird.

G-Man sagt "Reinstate Monica"
quelle
Für Debugging-Zwecke wäre es genauso einfach, sie exit_code="3"zum Testen
festzulegen
1
Ja, wjandrea hat gestern darauf hingewiesen .
G-Man sagt "Reinstate Monica"
12

exitist eine eingebaute Bash, also kannst du es nicht exec. Per Bashs Handbuch :

Der Exit-Status von Bash ist der Exit-Status des letzten im Skript ausgeführten Befehls. Wenn keine Befehle ausgeführt werden, ist der Exit-Status 0.

Zusammengenommen würde ich sagen, dass Ihre einzige Option darin besteht, Ihren gewünschten Exit-Status in einer Variablen zu speichern und dann exit $MY_EXIT_STATUSgegebenenfalls.

Solarshado
quelle
hmmm was denkst du über die Idee von @ G-man?
2
Vielleicht habe ich falsch verstanden, was Sie erreichen wollen. Wenn Sie nur versuchen zu setzen $?(obwohl ich nicht wirklich sicher bin, warum Sie das tun würden), scheint dies eine solide Antwort zu sein. Wenn Sie nur einen erfolglosen Wert festlegen möchten, falseist dies eine weitere Option.
Solarshado
10

Sie können eine Funktion schreiben, die den als Argument angegebenen Status zurückgibt oder 255wenn keiner angegeben ist. (Ich nenne es, retweil es seinen Wert "zurückgibt".)

ret() { return "${1:-255}"; }

und retanstelle Ihres Anrufs zu verwenden exit. Dies vermeidet die Ineffizienz beim Erstellen der Unter-Shell in der aktuell akzeptierten Antwort.

Einige Messungen.

time bash -c 'for i in {1..10000} ; do (exit 3) ; done ; echo $?'

auf meinem Computer dauert etwa 3,5 Sekunden.

 time bash -c 'ret(){ return $1 ; } ; for i in {1..10000} ; do ret 3 ; done ; echo $?'

Auf meinem Computer dauert es ungefähr 0,051 Sekunden, 70-mal schneller. Wenn Sie die Standardbehandlung verwenden, ist sie immer noch 60-mal schneller. Offensichtlich hat die Schleife etwas Overhead. Wenn ich den Körper der Schleife so ändere, dass er nur ist, :oder wenn sich truedie Zeit auf 0,025 halbiert, ist eine vollständig leere Schleife eine ungültige Syntax. Das Hinzufügen ;:zur Schleife zeigt, dass dieser minimale Befehl 0,007 Sekunden dauert, sodass der Schleifen-Overhead etwa 0,018 beträgt. Das Subtrahieren dieses Overheads von den beiden Tests zeigt, dass die retLösung über 100-mal schneller ist.

Natürlich ist dies eine synthetische Messung, aber die Dinge summieren sich. Wenn Sie alles 100-mal langsamer machen, als es sein muss, erhalten Sie langsame Systeme. 0.0

icarus
quelle
2
@iBug Der zusätzliche Speicherplatz wird nicht benötigt.
icarus
Guter Punkt zur Ineffizienz beim Erstellen der Sub-Shell. Ich habe gelesen, dass einige Muscheln in solchen Fällen klug genug sein könnten, um die Gabelung zu optimieren, aber diese Bash gehört nicht dazu.
G-Man sagt "Reinstate Monica"
3

Über exec exit 3... es würde versuchen, einen externen Befehl namens aufzurufen exit, aber es gibt keinen, so dass Sie den Fehler erhalten. Es verfügt über einen externen Befehl anstelle eines in die Schale eingebaut sein, da exec ersetzt die Schale vollständig. Was auch bedeutet , dass selbst wenn Sie einen externen Befehl aufgerufen hatte exit, exec exit 3würde nicht zurückkehren Ihre Shell - Skript , um fortzufahren, da die Schale nicht mehr da sein würde .

ilkkachu
quelle
1
Ich denke, Sie könnten es tun exec bash -c "exit 3", aber im Moment kann ich mir keinen Grund vorstellen, dies zu tun, anstatt nur exit 3.
David Z
1
@DavidZ wird in jedem Fall durch exec"ing" oder "nur exit" ing das Skript stoppen, was nicht so aussah, wie es die Frage wollte.
Ilkkachu
3

Sie können dies mit Awk tun:

awk 'BEGIN{exit 9}'

Oder Sed:

sed Q9 /proc/stat
Steven Penny
quelle
... oder mit einer Muschel:sh -c 'exit 9'
ilkkachu
1
@ilkkachu wenn du das tust, kannst du das auch (exit 9)in der akzeptierten Antwort tun
Steven Penny