Warum analysiert Bash überhaupt Dinge, die in die Umgebungsvariable eingefügt wurden?

9

Der Shellshock- Fehler in Bash funktioniert über Umgebungsvariablen. Ehrlich gesagt war ich überrascht von der Tatsache, dass es so ein Feature gibt wie:

"Weitergabe von Funktionsdefinitionen über env vars"

Daher ist diese Frage, obwohl sie möglicherweise nicht perfekt formuliert ist, die Frage nach einem Beispiel oder einem Fall, in dem diese Funktion erforderlich wäre.

Bonus. Haben auch andere Shells zsh, dash etc. diese Funktion?

Menschlichkeit UND Frieden
quelle
Es verwendet die env-Variablen, um Funktionsdefinitionen weiterzugeben. Was meinst du mit "Warum werden die Umgebungsvariablen nicht einfach verfügbar / zugänglich gehalten?" ?
Anthon
@Anthon Danke für den Kommentar. Vielleicht sollte ich klarer sein und umformulieren. Aus welchem ​​Grund ist es notwendig, Funktionsdefinitionen über env vars weitergeben zu können?
Menschlichkeit
1
Ich bin nicht 100% sicher, aber ich denke, dass GNU auf diese parallelWeise Funktionsdefinitionen verteilt, wenn mehrere Bash-Instanzen aufgerufen werden. Wenn dies nicht der Fall wäre, müssten diese in eine Datei geschrieben werden, die von jeder aufgerufenen Instanz eingelesen wird, und dann müssen Sie sich mit Problemen befassen, z. B. wann diese Datei entfernt werden kann.
Anthon
2
Dieser Thread hat eine Geschichte. Exportierte Funktionen sind jedoch verrückt . Wenn eine neue Shell alte ausführbare Shell-Befehle erben soll, beziehen Sie .dotdieselbe Datei wie die alte Shell. So wird es gemacht - und das macht Sinn - oder Sie geben der neuen Shell die Datei als Eingabe beim execIng. Sobald es eingelesen ist, wird die Datei ohnehin vom Kernel zwischengespeichert.
Mikesserv
@mikeserv Verstehe ich es richtig, dass ein großer Teil des Shellshocks mit dieser Funktion zusammenhängt, die sowieso nicht so wichtig ist?
Menschheit und

Antworten:

4

Wenn ein Skript ein anderes Skript aufruft, können Variablen des übergeordneten Skripts exportiert werden, die dann im untergeordneten Skript angezeigt werden. Das Exportieren von Funktionen ist eine offensichtliche Verallgemeinerung: Exportieren Sie die Funktion vom übergeordneten Element und machen Sie sie im untergeordneten Element sichtbar.

Die Umgebung ist die einzig bequeme Möglichkeit, wie ein Prozess beliebige Daten an seine untergeordneten Elemente weitergeben kann. Die Daten müssen in Zeichenfolgen zusammengefasst werden, die keine Null-Bytes enthalten, was für Shell-Funktionen keine Schwierigkeit darstellt. Es gibt andere mögliche Methoden, wie z. B. gemeinsam genutzte Speicherblöcke oder temporäre Dateien, die über Dateideskriptoren übergeben werden. Diese können jedoch Probleme mit Zwischenprogrammen verursachen, die nicht wissen, was sie damit tun sollen, oder sie schließen würden. Programme werden voraussichtlich in einer Umgebung ausgeführt, die Variablen enthält, die sie nicht kennen oder für die sie sich nicht interessieren, damit sie nicht überschrieben oder gelöscht werden.

Die Wahl, den Funktionsnamen als Namen der Umgebungsvariablen zu verwenden, ist seltsam. Zum einen bedeutet dies, dass eine exportierte Variable mit einer exportierten Funktion mit demselben Namen kollidiert.

Exportierte Funktionen sind eine alte Funktion. In der Bourne-Shell in SVR2 wurden Funktionen hinzugefügt und Funktionen in der Version 8-Shell exportiert, die im selben Jahr (1984) veröffentlicht wurde. In dieser Shell verwendeten Variablen und Funktionen denselben Namespace. Ich weiß nicht, wie der Funktionsexport funktioniert hat. Die Heirloom-Shell basiert auf einer Bourne-Variante, die Funktionen hat, diese aber nicht exportiert.

ATT ksh unterstützt angeblich das Exportieren von Funktionen, aber wenn ich mir die Quelle anschaue oder damit spiele, kann ich nicht sehen, dass dies ab ksh93u der Fall ist.

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Die Public Domain-Klone (pdksh, mksh), dash und zsh von Ksh unterstützen keine Exportfunktionen.

Gilles 'SO - hör auf böse zu sein'
quelle
1
Vielen Dank! Also, ohne Funktionen zu exportieren, geht die Funktionalität verloren, aber es gibt einige Shell wie dash, zsh und pdksh usw., denen diese Funktionalität fehlt. Lies ich das richtig?
Menschheit und
Aber wenn ich eine Funktion in Bash exportiere, geht sie in eine Variable wie BASH_FUNC_f%%=() { echo hi }. Warum sollte bash andere Umgebungsvariablen analysieren? Warum sollte es überhaupt analysiert werden, BASH_FUNC_g%%wenn ich nur anrufe f? (Anscheinend, vor dem Shellshock, wurde die Umgebungsvariable gerade aufgerufen foder g- aber ich frage mich immer noch, warum gsie analysiert worden wäre, wenn ich gmein Skript nie aufgerufen hätte)
Metamorphic
@Met Es müssen alle Umgebungsvariablen überprüft werden, um herauszufinden, welche Funktionsdefinitionen sind. Es könnte sich diese Tatsache merken und vermeiden, den Code einer Funktion zu analysieren, bis er zum ersten Mal benötigt wird, aber das wäre zusätzliche Komplexität für sehr wenig Gewinn. Es ist einfacher, nur einen Funktionstyp zu haben und nicht zwei ("normale Funktion" und "Funktion aus einer Umgebungsvariablen, die ein wenig analysiert werden muss").
Gilles 'SO - hör auf böse zu sein'
Unklar. Ich schlage vor, dass es naheliegend gewesen wäre f, (1) nach einer aufgerufenen Shell-Funktion zu suchen f, (2) nach einer aufgerufenen Umgebungsvariablen zu fsuchen und zu versuchen, sie zu analysieren, (3) zu prüfen Jede PATHKomponente für eine ausführbare Datei wird aufgerufen f. Wie könnte das Parsen jeder Umgebungsvariablen als Shell-Code beim Shell-Start als weniger kompliziertes Design erscheinen?
Metamorphic
@Metamorphic Sie schlagen vor, einen weiteren Schritt hinzuzufügen, der bei jedem Befehl ausgeführt werden muss. Sie müssten auch einen weiteren Schritt hinzufügen, wenn Sie Funktionen definieren oder die Definition aufheben (danach unset -f foomuss bash nicht mehr nach einer Funktionsdefinition fooin der Umgebung suchen ), wenn Sie Funktionen auflisten (wie gehen Sie declare -fanders vor, als alle Umgebungsvariablen zu lesen?) und an was auch immer ich sonst nicht denke. Ihr Design scheint nur einfacher zu sein, weil Sie das meiste davon weggelassen haben. Im Gegensatz dazu ist alles beim Start ein einziger Code, und danach funktioniert einfach alles.
Gilles 'SO - hör auf böse zu sein'