Ich habe hier gelesen, dass der Zweck von export
in einer Shell besteht darin, die Variable Subprozessen zur Verfügung zu stellen, die von der Shell gestartet werden.
Allerdings habe ich hier und hier auch gelesen, dass „Prozesse ihre Umgebung von ihrem Elternteil (dem Prozess, der sie gestartet hat) erben.“
Wenn dies der Fall ist, warum brauchen wir export
? Was übersehe ich?
Sind Shell-Variablen standardmäßig nicht Teil der Umgebung? Was ist der Unterschied?
Akzeptierte Antwort:
Ihre Annahme ist, dass Shell-Variablen in der Umgebung sind . Das ist falsch. Der export
Der Befehl definiert, dass ein Name überhaupt in der Umgebung vorhanden ist. Also:
a=1 b=2
export b
ergibt die aktuelle Shell wissend, dass $a
erweitert sich zu 1 und $b
bis 2, aber Unterprozesse wissen nichts über a
weil es nicht Teil der Umgebung ist (auch nicht in der aktuellen Shell).
Einige nützliche Tools:
set
:Nützlich zum Anzeigen der Parameter der aktuellen Shell, exportiert oder nichtset -k
:Setzt zugewiesene Argumente in der Umwelt. Betrachten Sief() { set -k; env; }; f a=1
set -a
:Weist die Shell an, jeden Namen, der in die Umgebung gesetzt wird, zu setzen. Wie das Setzen vonexport
vor jedem Einsatz. Nützlich für.env
Dateien, wie inset -a; . .env; set +a
.export
:Weist die Shell an, einen Namen in die Umgebung einzugeben. Export und Zuweisung sind zwei völlig unterschiedliche Vorgänge.env
:Als externer Befehlenv
kann Ihnen nur über das Ererbte berichten Umgebung, daher ist es nützlich für die Plausibilitätsprüfung.env -i
:Nützlich, um die Umgebung zu löschen, bevor ein Unterprozess gestartet wird.
Alternativen zu export
:
name=val command
# Zuweisung vor Befehl exportiert diesen Namen in den Befehl.declare/local -x name
# Exportiert Namen, besonders nützlich in Shell-Funktionen, wenn Sie vermeiden möchten, dass der Name außerhalb des Gültigkeitsbereichs verfügbar gemacht wird.set -a
# Exportiert jede folgende Zuweisung.
Motivation
Warum müssen Shells also ihre eigenen Variablen und eine andere Umgebung haben? Ich bin mir sicher, dass es einige historische Gründe gibt, aber ich denke, der Hauptgrund ist das Scoping. Die Umgebung ist für Unterprozesse, aber es gibt viele Operationen, die Sie in der Shell ausführen können, ohne einen Unterprozess zu forken. Angenommen, Sie schleifen:
for i in {0..50}; do
somecommand
done
Warum Speicher für somecommand
verschwenden indem Sie i
einfügen , indem er seine Umgebung größer macht, als er sein muss? Was ist, wenn der Variablenname, den Sie in der Shell gewählt haben, zufällig etwas Unbeabsichtigtes für das Programm bedeutet? (Zu meinen persönlichen Favoriten gehört DEBUG
und VERBOSE
. Diese Namen werden überall verwendet und sind selten angemessene Namensräume.)
Was ist die Umgebung, wenn nicht die Shell?
Um das Verhalten von Unix zu verstehen, müssen Sie sich manchmal die Systemaufrufe ansehen, die grundlegende API für die Interaktion mit dem Kernel und dem Betriebssystem. Hier betrachten wir die exec
Familie von Aufrufen, die die Shell verwendet, wenn sie einen Unterprozess erstellt. Hier ist ein Zitat aus der Manpage für exec(3)
(Hervorhebung von mir):
Das execle()
und execvpe()
Funktionen erlauben es dem Aufrufer, die Umgebung des ausgeführten Programms über das Argument envp anzugeben. Das envp-Argument ist ein Array von Zeigern auf nullterminierte Zeichenfolgen und muss durch einen NULL-Zeiger abgeschlossen werden. Die anderen Funktionen nehmen die Umgebung für das neue Prozessabbild aus der externen Variablen environ im aufrufenden Prozess.
Also schreiben Sie export somename
in der Shell würde dem Kopieren des Namens in das globale Wörterbuch environ
entsprechen in C. Aber Zuweisen von somename
ohne Exportieren wäre es genauso, als würde man es in C zuweisen, ohne es in die environ
zu kopieren Variable.