Definieren einer Variablen mit oder ohne Export


955

Wofür ist export?

Was ist der Unterschied zwischen:

export name=value

und

name=value

4
Tangential beachten Sie auch, dass export name=valuenicht tragbar ist. Versuchen Sie, je nachdem, was genau Sie möchten, name=value; export nameeine tragbare Lösung.
Tripleee

Antworten:


1054

export stellt die Variable für Unterprozesse zur Verfügung.

Das ist,

export name=value

bedeutet, dass der Variablenname für jeden Prozess verfügbar ist, den Sie über diesen Shell-Prozess ausführen. Wenn ein Prozess diese Variable verwenden soll, verwenden Sie exportden Prozess und führen Sie ihn über diese Shell aus.

name=value

bedeutet, dass der Variablenbereich auf die Shell beschränkt ist und keinem anderen Prozess zur Verfügung steht. Sie würden dies für (sagen wir) Schleifenvariablen, temporäre Variablen usw. verwenden.

Es ist wichtig zu beachten, dass das Exportieren einer Variablen diese nicht für übergeordnete Prozesse verfügbar macht. Das heißt, das Angeben und Exportieren einer Variablen in einem erzeugten Prozess macht sie in dem Prozess, der sie gestartet hat, nicht verfügbar.


105
Insbesondere exportiert export die Variable untergeordneten Prozessen über die Umgebung zur Verfügung.
Beano

15
Ich würde auch hinzufügen, dass wenn der Export in einer Datei ist, die Sie "quellen" (wie. Dateiname), es ihn auch in Ihre Arbeitsumgebung exportiert.
Rogerdpack

6
@rogerdpack kannst du das nicht ohne export machen? cat> blah \ na = hi \ n. bla; echo $ a; gibt 'hi' für mich aus.
David Winiecki

2
Schön, dass es auch ohne Export funktioniert. Ich denke also, wenn Sie eine Datei beschaffen, wenn Sie den Export verwenden, wird dies in
untergeordneten

19
Es gibt einen Randfall dazu; name=value command stellt die Variable im Unterprozess zur Verfügung command.
Oliver Charlesworth

254

Um zu veranschaulichen, was die anderen Antworten sagen:

$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$ 

9
Ein weiteres Beispiel dafüral$ foobar="Whatever" bash
Alun

70

Andere haben geantwortet, dass der Export die Variable für Subshells verfügbar macht, und das ist richtig, aber nur ein Nebeneffekt. Wenn Sie eine Variable exportieren, wird diese Variable in die Umgebung der aktuellen Shell eingefügt (dh die Shell ruft putenv(3)oder auf setenv(3)).
Die Umgebung eines Prozesses wird über exec hinweg vererbt, wodurch die Variable in Subshells sichtbar wird.

Bearbeiten (mit 5-Jahres-Perspektive): Dies ist eine dumme Antwort. Der Zweck von 'Export' besteht darin, Variablen "in der Umgebung von anschließend ausgeführten Befehlen zu sein", unabhängig davon, ob diese Befehle Unterschalen oder Unterprozesse sind. Eine naive Implementierung wäre, die Variable einfach in die Umgebung der Shell zu stellen, aber dies würde eine Implementierung unmöglich machen export -p.


6
Beachten Sie, dass dies nicht ganz stimmt. Beim bashExport wird die Variable zwar zur Umgebung der aktuellen Shell hinzugefügt, dies ist jedoch bei nicht der Fall dash. Es scheint mir, dass das Hinzufügen der Variablen zur Umgebung der aktuellen Shell der einfachste Weg ist, die Semantik von zu implementieren export, aber dieses Verhalten ist nicht vorgeschrieben.
William Pursell

7
Ich bin mir nicht sicher, was dashdamit zu tun hat. Das Originalplakat fragte speziell nach bash.
Seestern

14
Die Frage ist markiert bash, gilt aber gleichermaßen für jede Bourne-Shell-Variante. Zu spezifisch zu sein und Antworten zu geben, die nur für gelten, bashist ein großes Übel.
William Pursell

12
bashist die jQuery der Shell.
Potherca

2
export makes the variable available to subshells, and that is correctDies ist eine sehr verwirrende Verwendung der Terminologie. Subshells müssen keine exportVariablen erben. Unterprozesse tun.
Amit Naidu

62

Es wurde gesagt, dass es nicht notwendig ist, in Bash zu exportieren, wenn Subshells erzeugt werden, während andere das genaue Gegenteil sagten. Es ist wichtig , den Unterschied zwischen Subshells zu beachten (diejenigen , die erstellt werden (), ``, $()oder Schleifen) und Teilprozesse (Prozesse , die mit Namen aufgerufen werden, zum Beispiel eines wörtlichen bashin Ihrem Skript erscheinen).

  • Unterschalen wird Zugriff auf alle Variablen aus dem Elternteil haben, unabhängig von ihrer exportierten Zustand.
  • Sub - Prozesse werden nur die exportierten Variablen sehen.

Was diesen beiden Konstrukten gemeinsam ist, ist, dass keine der Variablen Variablen an die übergeordnete Shell zurückgeben kann.

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:

Es gibt noch eine weitere Quelle der Verwirrung: Einige denken, dass "gegabelte" Unterprozesse diejenigen sind, die keine nicht exportierten Variablen sehen. Normalerweise folgt auf fork () s sofort exec () s, und deshalb scheint es so, als ob man nach fork () sucht, während es tatsächlich exec () ist. Sie können Befehle ausführen, ohne zuerst fork () mit dem execBefehl auszuführen , und Prozesse, die mit dieser Methode gestartet werden, haben auch keinen Zugriff auf nicht exportierte Variablen:

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export

Beachten Sie, dass wir die parent:Zeile diesmal nicht sehen , da wir die übergeordnete Shell durch den execBefehl ersetzt haben, sodass nichts mehr übrig ist, um diesen Befehl auszuführen.


Ich habe noch nie eine Schleife gesehen, die (für sich) eine Unterschale erstellt hat. OTOH eine Pipeline (immer für andere Teile als die letzten, manchmal für die letzten, abhängig von Ihrer Shell, Version und Optionen). Backgrounding ( &) erstellt auch eine Subshell.
dave_thompson_085

Was ist mit diesen var=asdf bash -c 'echo $var'oder var=asdf exec bash -c 'echo $var'? Die Ausgabe ist asdf. Das ;macht einen Unterschied, wenn es nach der Variablendefinition platziert wird. Was wäre die Erklärung? Es sieht so aus, als ob die var(ohne ;) Rücksicht auf den hervorgebrachten Unterprozess irgendwie aufgrund der Ursprungsschale nichts damit zu tun hat. echo $varGibt nichts aus, wenn es in der zweiten Zeile ausgeführt wird. Aber eine Linie var=asdf bash -c 'echo $var'; echo $vargibt asdf\nasdf.
4xy

31

export NAME=value für Einstellungen und Variablen, die für einen Unterprozess von Bedeutung sind.

NAME=value für temporäre oder Schleifenvariablen, die für den aktuellen Shell-Prozess privat sind.

Markiert detaillierter exportden Variablennamen in der Umgebung, die bei der Erstellung in einen Unterprozess und dessen Unterprozesse kopiert wird. Kein Name oder Wert wird jemals aus dem Unterprozess zurückkopiert.

  • Ein häufiger Fehler besteht darin, ein Leerzeichen um das Gleichheitszeichen zu setzen:

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
  • Nur die exportierte Variable ( B) wird vom Unterprozess gesehen:

    $ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
    A is . B is Bob
  • Änderungen im Unterprozess ändern die Haupt-Shell nicht:

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
  • Für den Export markierte Variablen haben Werte, die beim Erstellen des Unterprozesses kopiert werden:

    $ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 
    Subprocess 1 has B=Bob
    Subprocess 2 has B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
  • Nur exportierte Variablen werden Teil der Umgebung ( man environ):

     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob

Jetzt sollte es so klar sein wie die Sommersonne! Vielen Dank an Brain Agnew, Alexp und William Prusell.


12

export stellt die Variable allen Shells zur Verfügung, die von der aktuellen Shell gegabelt wurden.


11

Es ist zu beachten, dass Sie eine Variable exportieren und später den Wert ändern können. Der geänderte Wert der Variablen steht untergeordneten Prozessen zur Verfügung. Nachdem der Export für eine Variable festgelegt wurde, müssen Sie export -n <var>die Eigenschaft entfernen.

$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset

Vielen Dank, dies sind genau die Informationen, nach denen ich gesucht habe, da ich ein Skript gesehen habe, das Umgebungsvariablen verwendet und diese dann mit einem neuen Wert "erneut exportiert" hat, und mich gefragt habe, ob dies erforderlich ist.
Mike Lippert

8

Wie Sie vielleicht bereits wissen, ermöglicht UNIX Prozessen, eine Reihe von Umgebungsvariablen zu haben, bei denen es sich um Schlüssel / Wert-Paare handelt, wobei sowohl Schlüssel als auch Wert Zeichenfolgen sind. Das Betriebssystem ist dafür verantwortlich, diese Paare für jeden Prozess separat aufzubewahren.

Das Programm kann über diese UNIX-API auf seine Umgebungsvariablen zugreifen:

  • char *getenv(const char *name);
  • int setenv(const char *name, const char *value, int override);
  • int unsetenv(const char *name);

Prozesse erben auch Umgebungsvariablen von übergeordneten Prozessen. Das Betriebssystem ist dafür verantwortlich, eine Kopie aller "Envars" zu erstellen, wenn der untergeordnete Prozess erstellt wird.

Bash ist unter anderem in der Lage, seine Umgebungsvariablen auf Benutzeranforderung festzulegen. Dafür gibt exportes.

exportist ein Bash-Befehl zum Festlegen der Umgebungsvariablen für Bash. Alle mit diesem Befehl festgelegten Variablen würden von allen Prozessen geerbt, die dieser Bash erstellen würde.

Mehr zur Umwelt in Bash

Eine andere Art von Variable in Bash ist die interne Variable. Da Bash nicht nur eine interaktive Shell ist, ist es tatsächlich ein Skriptinterpreter, wie jeder andere Interpreter (z. B. Python), der in der Lage ist, seine eigenen Variablen zu behalten. Es sollte erwähnt werden, dass Bash (im Gegensatz zu Python) nur String-Variablen unterstützt.

Notation zum Definieren von Bash-Variablen ist name=value. Diese Variablen bleiben in Bash und haben nichts mit Umgebungsvariablen zu tun, die vom Betriebssystem verwaltet werden.

Weitere Informationen zu Shell-Parametern (einschließlich Variablen)

Erwähnenswert ist auch, dass laut Bash Referenzhandbuch:

Die Umgebung für einfache Befehle oder Funktionen kann vorübergehend erweitert werden, indem Parameterzuweisungen vorangestellt werden, wie unter Shell-Parameter beschrieben . Diese Zuweisungsanweisungen wirken sich nur auf die Umgebung aus, die von diesem Befehl angezeigt wird.


Um es zusammenzufassen:

  • exportwird verwendet, um Umgebungsvariablen im Betriebssystem festzulegen. Diese Variable steht allen untergeordneten Prozessen zur Verfügung, die vom aktuellen Bash-Prozess erstellt wurden.
  • Die Bash-Variablennotation (Name = Wert) wird verwendet, um lokale Variablen festzulegen, die nur für den aktuellen Bash-Prozess verfügbar sind
  • Die Bash-Variablennotation, die einem anderen Befehl vorangestellt ist, erstellt eine Umgebungsvariable nur für den Umfang dieses Befehls.

1
Bash-Vars unterstützen nicht so viele Typen wie Python, haben jedoch String, Integer und zwei Arten von Arrays ('indiziert' / traditionell und 'assoziativ', ähnlich wie awk-Array, Perl-Hash oder Python-Diktat). Andere Muscheln variieren; Nur String ist portabel .
Dave_thompson_085

7

Die akzeptierte Antwort impliziert dies, aber ich möchte die Verbindung zu eingebauten Shell explizit machen:

Wie bereits erwähnt, exportwird eine Variable sowohl für die Shell als auch für untergeordnete Elemente verfügbar gemacht. Wenn exportes nicht verwendet wird, ist die Variable nur in der Shell verfügbar, und nur in die Shell eingebaute Variablen können darauf zugreifen.

Das ist,

tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin

3

Hier ist noch ein weiteres Beispiel:

VARTEST="value of VARTEST" 
#export VARTEST="value of VARTEST" 
sudo env | grep -i vartest 
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}" 
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'  

Nur mit export VARTEST ist der Wert von VARTEST in sudo bash -c '...' verfügbar!

Weitere Beispiele siehe:


3

Zwei der Entwickler von UNIX, Brian Kernighan und Rob Pike, erklären dies in ihrem Buch "The UNIX Programming Environment". Google für den Titel und Sie finden leicht eine PDF-Version.

Sie befassen sich mit Shell-Variablen in Abschnitt 3.6 und konzentrieren sich auf die Verwendung des exportBefehls am Ende dieses Abschnitts:

Wenn Sie den Wert einer Variablen in Sub-Shells zugänglich machen möchten, sollte der Exportbefehl der Shell verwendet werden. (Sie könnten darüber nachdenken, warum es keine Möglichkeit gibt, den Wert einer Variablen von einer Unter-Shell in die übergeordnete Variable zu exportieren.)


2

Nur um den Unterschied zwischen einer exportierten Variablen in der Umgebung (env) und einer nicht exportierten Variablen in der Umgebung zu zeigen:

Wenn ich das mache:

$ MYNAME=Fred
$ export OURNAME=Jim

dann erscheint nur $ OURNAME in der Umgebung. Die Variable $ MYNAME befindet sich nicht in der Umgebung.

$ env | grep NAME
OURNAME=Jim

Die Variable $ MYNAME ist jedoch in der Shell vorhanden

$ echo $MYNAME
Fred

1

Standardmäßig sind in einem Skript erstellte Variablen nur für die aktuelle Shell verfügbar. Untergeordnete Prozesse (Unter-Shells) haben keinen Zugriff auf Werte, die festgelegt oder geändert wurden. Damit untergeordnete Prozesse die Werte anzeigen können, muss der Befehl export verwendet werden.


0

Obwohl in der Diskussion nicht explizit erwähnt, ist es NICHT erforderlich, den Export zu verwenden, wenn eine Subshell aus Bash heraus erzeugt wird, da alle Variablen in den untergeordneten Prozess kopiert werden.


Bitte erläutern Sie, wie das, was Sie sagen, den Antworten mit den obigen Beispielen direkt zu widersprechen scheint.
Mike Lippert

Dies ist der richtige Weg, wenn Sie nicht möchten, dass die Variablen global exportiert werden, sondern nur für den Unterprozess verfügbar sind! Vielen Dank.
Jtblin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.