Ich habe den nächsten Codeausschnitt aus „ config.status
generiert von“ zitiert configure
.
if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
Was bedeutet „do“ im Codeausschnitt { (exit 1); exit 1; };
? Welchen Zweck hat „doing“ nur exit
in einer Subshell?
Antwort1
Die Ausführung (exit 1);
ist die einfachste Möglichkeit, einen Trap auszulösen ERR
. Wenn er aktiv ist, wird auch ein sofortiger Ausgang ausgelöst set -e
. (Um den Fehlerzustand auszulösen, muss ein Befehl fehlschlagen; exit
ein Fehlerwert in einer Subshell führt dazu, dass die Subshell fehlschlägt.)
exit 1;
wird keines von beidem tun.
{(exit 1); exit 1;}
Kann also verwendet werden, um zunächst den ERR
Trap zu erzeugen, der für Debugging-Zwecke hilfreich sein kann, und dann das Skript mit einer Fehleranzeige zu beenden.
Aber das ist nicht das, was in Dateien passiert autoconf
. autoconf
Skripte verlassen sich auf die EXIT
Trap, um temporäre Dateien zu bereinigen, die während der Ausführung erstellt wurden. Die meisten Shells, einschließlich, bash
setzen den Status aus dem im exit
Befehl angegebenen Wert, bevor die EXIT
Trap aufgerufen wird. Dadurch kann die EXIT
Trap erkennen, ob sie aufgrund eines Fehlers oder einer normalen Beendigung aufgerufen wurde, und es kann auch sicherstellen, dass der Beendigungsstatus am Ende des Trap-Vorgangs korrekt festgelegt ist.
Allerdings scheinen einige Shells nicht zu kooperieren. Hier ist ein Zitat aus demautoconf
Handbuch:
Einige Shell-Skripte, wie die von generierten
autoconf
, verwenden vor dem Beenden einen Trap zum Bereinigen. Wenn der letzte Shell-Befehl mit einem Status ungleich Null beendet wurde, wird auch der Trap mit einem Status ungleich Null beendet, sodass der Aufrufer erkennen kann, dass ein Fehler aufgetreten ist.Leider ignoriert ein Exit-Trap in manchen Shells, wie z. B. Solaris
/bin/sh
, das Argument des Exit-Befehls. In diesen Shells kann ein Trap nicht feststellen, ob er durch einfaches Exit oder durch Exit 1 aufgerufen wurde. Anstatt exit direkt aufzurufen, verwenden Sie dasAC_MSG_ERROR
Makro, das einen Workaround für dieses Problem bietet.
Die Problemumgehung besteht darin, sicherzustellen, dass $?
der Exit-StatusVorder exit
Befehl wird ausgeführt, sodass er definitiv diesen Wert hat, wenn die EXIT
Falle ausgeführt wird. Und tatsächlich ist es das AC_MSG_ERROR
Makro, das diesen merkwürdigen Code einfügt, komplett mit redundanten Klammern.
Antwort2
Dies hat meines Erachtens keinen Zweck, durch das Starten und sofortige Beenden einer Subshell lässt sich nichts direkt erreichen.
Solche Dinge sind höchstwahrscheinlich ein Nebeneffekt der automatischen Codegenerierung – in manchen Fällen werden in der Subshell möglicherweise andere Befehle ausgeführt, bei denen dies exit 1
sinnvoll ist. Letztendlich besteht eine gute Chance, dass der Generierungscode irgendwie vereinfacht wird, indem er in manchen Fällen Anweisungen einfügen kann, die keine Funktion haben, und jedes Mal „sauberen Code“ zu generieren, ist komplexer. Entweder das oder der Code, der das Obige generiert hat, ist einfach schlecht geschrieben :)
Der großzügige Gebrauch von {...}
ist ein weiteres Beispiel dafür. Die meisten von ihnen sind redundant, aber es ist einfacher, Code zu schreiben, der sie in jedem Fall einfügt (vielleicht möchten Sie in einigen Fällen die Ausgabe/Eingabe des Blocks umleiten), als diejenigen zu kennzeichnen, bei denen sie nicht benötigt werden, und sie wegzulassen.
Antwort3
(exit 1)
ist ein einfacher, wahrscheinlich der einfachste Weg, einen bestimmten Exit-Code zu erhalten (im Spezialfall 1 gibt es natürlich einfachere Wege). Aber das ist in diesem Fall nicht der Grund, da der Exit-Code nicht untersucht wird.
Der Zweck des Einfügens exit
einer Subshell kann darin bestehen, das Skript nicht zu beenden (obwohl exit zum Generieren eines bestimmten Exit-Codes verwendet wird).