Ich bin gerade auf ein Problem gestoßen, das mir zeigt, dass mir der Umfang der Shell-Variablen nicht klar ist.
Ich habe versucht bundle install
, einen Ruby-Befehl zu verwenden, der den Wert von verwendet $GEM_HOME
, um seine Arbeit zu erledigen. Ich hatte festgelegt $GEM_HOME
, aber der Befehl ignorierte diesen Wert, bis ich export
wie in verwendet habe export GEM_HOME=/some/path
.
Ich habe gelesen, dass dies die Variable irgendwie "global" macht (auch als Umgebungsvariable bekannt ), aber ich verstehe nicht, was das bedeutet. Ich kenne globale Programme, aber nicht programmübergreifend.
Da meine Einstellung solcher Variablen nur für die aktuelle Shell-Sitzung gilt, wie würde ich sie beispielsweise für einen daemonisierten Prozess festlegen?
Welche Bereiche können Shell-Variablen haben?
quelle
FOO=bar
, legt dies den Wert für den aktuellen Shell-Prozess fest. Wenn ich dann ein Programm wie (bundle install
) ausführe , wird ein untergeordneter Prozess erstellt, auf den nicht zugegriffen werden kannFOO
. Aber wenn ich gesagt hatteexport FOO=bar
, das Kind Prozess (und deren Nachkommen) würde den Zugang zu ihm haben. Einer von ihnen könnte wiederum anrufenexport FOO=buzz
, um den Wert für seine NachkommenFOO=buzz
zu ändern , oder nur , um den Wert nur für sich selbst zu ändern. Ist das ungefähr richtig?Zumindest unter
ksh
undbash
können Variablen drei Bereiche haben, nicht zwei, wie alle verbleibenden Antworten aktuell aussagen.Zusätzlich zu den Bereichen für exportierte (dh Umgebungs) Variablen und nicht exportierte Shell-Variablen gibt es auch einen dritten engeren Bereich für lokale Funktionsvariablen.
Variablen, die in Shell-Funktionen mit dem
typeset
Token deklariert wurden, sind nur in den Funktionen sichtbar, in denen sie deklariert wurden, und in (Unter-) Funktionen, die von dort aufgerufen wurden.Dieser
ksh
/bash
Code:erzeugt diese Ausgabe:
Wie Sie sehen, wird die exportierte Variable an den ersten drei Positionen angezeigt, die nicht exportierten Variablen werden nicht außerhalb der aktuellen Shell angezeigt und die lokale Variable der Funktion hat keinen Wert außerhalb der Funktion. Der letzte Test zeigt überhaupt keine Werte an, da exportierte Variablen nicht zwischen Shells geteilt werden, dh sie können nur geerbt werden und der geerbte Wert kann danach nicht von der übergeordneten Shell beeinflusst werden.
Beachten Sie, dass sich das letztgenannte Verhalten stark von dem von Windows unterscheidet, in dem Sie Systemvariablen verwenden können, die vollständig global sind und von allen Prozessen gemeinsam genutzt werden.
quelle
Sie sind prozessbezogen
Die anderen Antworten haben mir geholfen zu verstehen, dass es bei dem Shell-Variablenbereich um Prozesse und deren Nachkommen geht .
Wenn Sie einen Befehl wie
ls
in der Befehlszeile eingeben, veranlassen Sie einen Prozess, dasls
Programm auszuführen . Der neue Prozess hat Ihre Shell als übergeordnetes Element.Jeder Prozess kann seine eigenen "lokalen" Variablen haben, die nicht an untergeordnete Prozesse übergeben werden. Es können auch Umgebungsvariablen gesetzt werden. Mit
export
wird eine Umgebungsvariable erstellt. In beiden Fällen wird die Variable für nicht verwandte Prozesse (Peers des Originals) nicht angezeigt. Wir steuern nur, was untergeordnete Prozesse sehen.Angenommen, Sie haben eine Bash-Shell, die wir A nennen. Sie geben ein
bash
, wodurch eine untergeordnete Prozess-Bash-Shell erstellt wird, die wir B nennen. Alles, was Sieexport
in A aufgerufen haben, wird weiterhin in B gesetzt.Nun, in B, sagst du
FOO=b
. Eines von zwei Dingen wird passieren:FOO
, wird eine lokale Variable erstellt. Kinder von B werden es nicht bekommen (außer B ruft anexport
).FOO
, wird sie es für sich selbst verändern und ihre anschließend gegabelt Kinder . Kindern von B wird der von B zugewiesene Wert angezeigt. Dies hat jedoch keinerlei Auswirkungen auf A.Hier ist eine kurze Demo.
All dies erklärt mein ursprüngliches Problem: Ich habe
GEM_HOME
in meiner Shell festgelegt, aber als ich anriefbundle install
, wurde ein untergeordneter Prozess erstellt. Da ich nicht verwendet hatteexport
, hat der untergeordnete Prozess die Shell nicht erhaltenGEM_HOME
.Export wird abgebrochen
Sie können eine Variable "dekomprimieren" - verhindern, dass sie an untergeordnete Variablen übergeben wird -, indem Sie verwenden
export -n FOO
.quelle
Die beste Erklärung für den Export ist die folgende:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Die in einer Subshell oder Child-Shell festgelegte Variable ist nur für die Subshell sichtbar, in der sie definiert ist. Die exportierte Variable ist eigentlich eine Umgebungsvariable. Um klar zu sein,
bundle install
führt Ihr eine eigene Shell aus, die die nicht sieht,$GEM_HOME
es sei denn, es wird eineenvironment
Variable namens exportiert.Die Dokumentation zum Variablenumfang finden Sie hier:
http://www.tldp.org/LDP/abs/html/subshells.html
quelle
FOO=bar
; du musst es benutzenexport
, um eins zu machen. Frage entsprechend korrigiert.Wie erwartet gibt es eine Hierarchie variabler Bereiche.
Umgebung
Der äußerste Bereich ist die Umwelt. Dies ist der einzige Bereich, der vom Betriebssystem verwaltet wird und daher für jeden Prozess garantiert vorhanden ist. Wenn ein Prozess gestartet wird, erhält er eine Kopie der Umgebung seines Elternteils, wonach beide unabhängig werden: Durch Ändern der Umgebung des Kindes wird die Umgebung des Elternteils nicht geändert, und durch Ändern der Umgebung des Elternteils wird die eines bereits vorhandenen Kindes nicht geändert.
Shell-Variablen
Shells haben ihre eigene Vorstellung von Variablen. Hier wird es etwas verwirrend.
Wenn Sie einer Variablen in einer Shell einen Wert zuweisen und diese Variable bereits in der Umgebung vorhanden ist, erhält die Umgebungsvariable den neuen Wert. Befindet sich die Variable jedoch noch nicht in der Umgebung, wird sie zur Shell- Variablen. Shell-Variablen existieren nur innerhalb des Shell-Prozesses, ähnlich wie Ruby-Variablen nur innerhalb eines Ruby-Skripts existieren. Sie werden niemals von untergeordneten Prozessen geerbt.
Hier kommt das
export
Schlüsselwort ins Spiel. Es kopiert eine Shell-Variable in die Umgebung des Shell-Prozesses, sodass untergeordnete Prozesse erben können.Lokale Variablen
Lokale Variablen sind Shell-Variablen, die sich auf die sie enthaltenden Codeblöcke beziehen. Sie deklarieren lokale Variablen mit dem
typeset
Schlüsselwort (portable) oderlocal
oderdeclare
(Bash). Wie andere Shell-Variablen werden lokale Variablen nicht an untergeordnete Prozesse vererbt. Auch lokale Variablen können nicht exportiert werden.quelle