Was bedeutet `{{(Ausfahrt 1); Ausfahrt 1; }; } `meine?

28

Ich habe das nächste Code-Snippet zitiert, das von config.statusgeneriert wurde 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 macht { (exit 1); exit 1; };man im Code-Snippet ? Was ist der Zweck nur exitin einer Subshell zu tun?

MS.Kim
quelle

Antworten:

33

Das Ausführen (exit 1);ist die einfachste Art, eine ERRFalle auszulösen . Es wird auch ein sofortiges Verlassen ausgelöst, wenn dies set -ewirksam ist. (Zum Auslösen der Fehlerbedingung muss ein Befehl fehlschlagen. exitWenn ein Fehlerwert in einer Subshell angegeben wird, schlägt die Subshell fehl.)

exit 1; wird keines dieser Dinge tun.

So {(exit 1); exit 1;}kann den zum ersten Produkten verwendet wird ERRFall, die für Debugging - Zwecke nützlich etwas tun könnte, und dann das Skript mit einer Fehleranzeige beenden.

Aber das ist nicht das, was in autoconfDateien vor sich geht. autoconfSkripte verlassen sich auf die EXITFalle, um temporäre Dateien zu bereinigen, die während des Laufs erstellt wurden. Die meisten Shells, einschließlich bash, setzen den Status anhand des im exitBefehl angegebenen Werts, bevor sie den EXITTrap aufrufen . Auf diese Weise kann der EXITTrap erkennen, ob er aufgrund eines Fehlers oder einer normalen Beendigung aufgerufen wurde, und er kann auch sicherstellen, dass der Beendigungsstatus am Ende des Trap-Vorgangs korrekt festgelegt ist.

Anscheinend arbeiten jedoch einige Muscheln nicht zusammen. Hier ist ein Zitat aus dem autoconfHandbuch :

Einige Shell-Skripte, beispielsweise die von generierten autoconf, bereinigen vor dem Beenden mit einem Trap. Wenn der letzte Shell-Befehl mit einem Status ungleich Null beendet wurde, wird der Trap auch mit einem Status ungleich Null beendet, sodass der Aufrufer feststellen kann, dass ein Fehler aufgetreten ist.

Leider /bin/shignoriert eine Exit-Trap in einigen Shells, wie z. B. Solaris , das Argument des Befehls exit. In diesen Shells kann ein Trap nicht feststellen, ob er durch einfaches Beenden oder durch Beenden von 1 aufgerufen wurde. Verwenden Sie den AC_MSG_ERRORMakro, der eine Problemumgehung für dieses Problem aufweist, anstatt Exit direkt aufzurufen .

Die Problemumgehung besteht darin, vor der Ausführung des Befehls sicherzustellen, dass $?dieser den Exit-Status hat , damit er bei der Ausführung des Traps definitiv diesen Wert hat . Und tatsächlich ist es das Makro, das diesen seltsamen Code mit redundanten Klammern einfügt.exitEXITAC_MSG_ERROR

rici
quelle
Warum nicht einfach ausführen falsestatt (exit 1)?
Ruslan
3
@ Ruslan: Zwei Probleme. (1) Das Wichtigste: falseSie können den Statuscode nicht festlegen, und es gibt keine Garantie dafür, welcher Nicht-Null-Status zurückgegeben wird. (2) falseist normalerweise kein integrierter Prozess, sodass ein untergeordneter Prozess erforderlich ist. Im Gegensatz dazu können die meisten Muscheln das Laichen eines Kindes vermeiden (exit 1).
rici
8

Dies hat meines Erachtens keinen Sinn, es gibt nichts, was direkt durch Starten einer Unterschale und sofortiges Beenden erreicht werden kann.

Solche Dinge sind höchstwahrscheinlich ein Nebeneffekt der automatischen Codegenerierung. In einigen Fällen werden möglicherweise andere Befehle in der Subshell ausgeführt, wenn das exit 1sinnvoll ist. Letztendlich besteht eine gute Chance, dass der Generierungscode auf irgendeine Weise vereinfacht wird, indem einige Anweisungen eingefügt werden, die in einigen Fällen keine Funktion haben, und die Generierung von 'sauberem Code' jedes Mal komplexer ist. Entweder das oder der Code, der das oben Genannte generiert hat, ist nur schlecht geschrieben :)

Die liberale Verwendung 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 (in einigen Fällen möchten Sie möglicherweise die Ausgabe / Eingabe des Blocks umleiten), anstatt die zu unterscheiden diejenigen, wo sie nicht benötigt werden und lassen sie weg.

Graeme
quelle
Es hat einen Zweck. Siehe @ ricis Antwort.
Old Pro
1

(exit 1)Dies ist ein einfacher, wahrscheinlich der einfachste Weg, einen bestimmten Exit-Code zu erhalten (im Sonderfall 1 gibt es natürlich einfachere Wege). Dies ist jedoch in diesem Fall nicht der Grund, da der Exit-Code nicht geprüft wird.

Der Zweck des exitEinfügens einer Subshell kann darin bestehen, das Skript nicht zu beenden (obwohl exit zur Generierung eines bestimmten Beendigungscodes verwendet wird).

Hauke ​​Laging
quelle