Warum benötigt POSIX bestimmte Shell-Built-Ins, um extern implementiert zu werden?

18

Aus dieser Frage, ob printf für yash integriert ist , ergibt sich diese Antwort, die den POSIX-Standard zitiert .

Die Antwort weist darauf hin, dass die POSIX-Suchsequenz darin besteht, eine externe Implementierung des gewünschten Befehls zu finden, und dann, wenn die Shell sie als eingebaut implementiert hat, das eingebaute auszuführen. (Für Built-Ins, die keine speziellen Built-Ins sind .)

Warum muss für POSIX eine externe Implementierung vorhanden sein, bevor eine interne Implementierung ausgeführt werden kann?

Es scheint ... willkürlich, also bin ich neugierig.

Studog
quelle
Ich glaube, das ist eine Möglichkeit, Builtins zu aktivieren / deaktivieren, wenn gewünscht / erforderlich.
Isaac
2
Deaktivieren Sie die eingebaute durch Entfernen der externen Implementierung? Jetzt sind keine Namensbefehle printfverfügbar.
Studog
@studog, erstellen Sie also eine leere Datei mit demselben Namen wie die eingebaute, aktivieren Sie das Ausführungsbit und speichern Sie es in einem Verzeichnis in Ihrem PATH. : P
Wildcard
@Wildcard Eine streng konforme Shell würde dann beim Durchsuchen der den Namen sehen PATHund dann das eingebaute Hilfsprogramm aufrufen, nicht das externe Skript. Was ist, wenn Sie das externe Skript in Ihrem Pfad aufrufen möchten? Hmm ... Dies scheint eine Tabelle zu erfordern, die die verschiedenen Möglichkeiten beschreibt. Es gibt eine hier , aber für mich ergibt das keinen Sinn.
Kusalananda
@Kusalananda, wieder dein erster Satz, das war mein Punkt. Daher habe ich gesagt, eine leere Datei zu erstellen .
Wildcard

Antworten:

15

Dies ist eine "als ob" -Regel.

Einfach ausgedrückt: Das Verhalten der Shell, wie Benutzer es sehen, sollte sich nicht ändern, wenn eine Implementierung entscheidet, einen externen Standardbefehl auch als integrierte Shell verfügbar zu machen.

Der Kontrast, den ich unter /unix//a/496291/5132 zwischen den Verhaltensweisen der (einerseits) PD Korn-, MirBSD Korn- und Heirloom Bourne-Shells zeigte; (auf der anderen Seite) die Schalen Z, 93 Korn, Bourne Again und Debian Almquist; und (auf der Greifhand) die Watanabe-Muschel hebt dies hervor.

Für die Shells, die nicht printfals eingebaut haben, führt das Entfernen /usr/binvon zu PATHeinem printfAbbruch der Arbeit. Das POSIX-konforme Verhalten, das die Watanabe-Shell im konformen Modus zeigt, führt zum gleichen Ergebnis. Das Verhalten der Shell mit printfintegriertem Befehl ist so, als würde sie einen externen Befehl aufrufen.

Während sich das Verhalten aller nicht konformen Shells nicht ändert, wenn /usr/binentfernt wird PATH, und sie sich nicht so verhalten, als würden sie einen externen Befehl aufrufen.

Was der Standard Ihnen garantieren möchte, ist, dass Shells alle Arten von normalerweise externen Befehlen einbauen können (oder sie als eigene Shell-Funktionen implementieren), und dass Sie mit den eingebauten Funktionen immer noch dasselbe Verhalten erzielen wie Sie mit den externen Befehlen, wenn Sie einstellen PATH, dass die Befehle nicht gefunden werden. PATHbleibt Ihr Werkzeug zur Auswahl und Steuerung der Befehle, die Sie aufrufen können.

(Wie unter /unix//a/448799/5132 erläutert , haben die Leute vor Jahren die Persönlichkeit ihres Unix durch Ändern der Einstellungen ausgewählt PATH.)

Man könnte meinen, dass die Ausführung des Befehls immer funktioniert, unabhängig davon, ob er gefunden PATH wird oder nicht, in der Tat der Punkt ist, an dem normalerweise externe Befehle eingebaut werden. (Aus diesem Grund hat mein nosh-Toolset printenvin Version 1.38 einen integrierten Befehl erhalten. Dies ist jedoch keine Shell.)

Der Standard gibt Ihnen jedoch die Garantie, dass Sie für reguläre externe Befehle, die nicht in der Shell ausgeführt werden, dasselbe Verhalten wie für PATHandere Nicht-Shell-Programme sehen, die die execvpe()Funktion aufrufen , und dass die Shell dies auf magische Weise nicht kann (scheinbar) normale externe Befehle ausführen, die andere Programme mit denselben nicht finden können PATH. Alles funktioniert aus Sicht des Benutzers in sich selbst und PATHist das Werkzeug zur Steuerung seiner Funktionsweise.

Weitere Lektüre

JdeBP
quelle
13

Das ist ziemlich absurd und deshalb implementiert es keine Shell im Standardmodus.

Die Standard Begründung und ihre Erläuterung Beispiel legen nahe , dass dies ein verpfuschten Versuch war , eine zu haben , regelmäßig mit einem Pfad verbunden sind eingebaut, und lassen Sie die Überschreibung Benutzer sie von ihren eigenen binären , bevor es in erscheinen, die PATH(z. B. eine printfintegrierte in Zusammenhang mit /usr/bin/printfkönnte durch den /foo/bin/printfexternen Befehl durch Setzen überschrieben werden PATH=/foo/bin:$PATH).

Der Standard verlangte dies jedoch nicht, sondern etwas völlig anderes (und auch nutzlos und unerwartet).

Sie können mehr darüber in diesem Fehlerbericht lesen . Zitat aus dem endgültig akzeptierten Text :

Viele vorhandene Implementierungen führen eine reguläre integrierte Suche aus, ohne eine PATH-Suche durchzuführen. Dieses Verhalten stimmt nicht mit dem normativen Text überein, und es ermöglicht Skriptautoren nicht, reguläre integrierte Dienstprogramme über einen speziell gestalteten PATH zu überschreiben. Darüber hinaus wird begründet, dass Autoren die Möglichkeit haben sollen, integrierte Funktionen durch Ändern von PATH zu überschreiben. Dies wird jedoch im normativen Text nicht angegeben .

FWIW, ich glaube auch nicht, dass es eine Shell gibt, die die überarbeiteten Anforderungen aus dem akzeptierten Text implementiert.

Mosvy
quelle
Siehe auch die Diskussion unter article.gmane.org/gmane.comp.standards.posix.austin.general/… (und es gab mehrere andere).
Stéphane Chazelas
Also github.com/att/ast/issues/370 (long)
Stéphane Chazelas
Nein (z. B. ein mit / usr / bin / printf verknüpftes printf könnte durch den externen Befehl / foo / bin / printf überschrieben werden, indem PATH = / foo / bin: $ PATH festgelegt wird). , das ist falsch. Das Vorhandensein von einem / beiden / irgendeinem von /usr/bin/printfoder /foo/bin/printfim PATH aktiviert den eingebauten printf. Das einzige, was ein (im PATH) fehlender externer printfWille tut, ist das Deaktivieren des eingebauten. (Nach dem Buchstaben der Spezifikation).
Isaac