Eine Kopie der Umgebung breitet sich in Unterschalen aus. Dies funktioniert also wie folgt:
$ export MY_VAR=200
$ bash
$ echo $MY_VAR
200
Da es sich jedoch um eine Kopie handelt, können Sie diesen Wert nicht auf die übergeordnete Shell übertragen - zumindest nicht durch Ändern der Umgebung.
Es hört sich so an, als ob Sie tatsächlich einen Schritt weiter gehen möchten, nämlich etwas, das sich wie eine globale Variable verhält und von "Geschwister" -Shells gemeinsam genutzt wird, die separat vom übergeordneten Element initiiert wurden - wie Ihr neuer Tab in Gnome Terminal.
Meistens lautet die Antwort "Sie können nicht, weil Umgebungsvariablen nicht so funktionieren". Es gibt jedoch noch eine andere Antwort: Sie können immer etwas auf den Kopf stellen. Ein Ansatz wäre, den Wert der Variablen in eine Datei zu schreiben ~/.myvar
und ihn dann in die Datei einzuschließen ~/.bashrc
. Dann beginnt jede neue Shell mit dem Wert, der aus dieser Datei gelesen wurde.
Sie können noch einen Schritt weiter gehen - geben Sie ~/.myvar
das Format ein MYVAR=200
und legen Sie fest PROMPT_COMMAND=source ~/.myvar
, dass der Wert jedes Mal neu gelesen wird, wenn Sie eine neue Eingabeaufforderung erhalten. Es ist immer noch nicht ganz eine gemeinsame globale Variable, aber es fängt an, wie es zu handeln. Es wird jedoch erst aktiviert, wenn eine Eingabeaufforderung zurückkommt. Dies kann je nach dem, was Sie versuchen, eine ernsthafte Einschränkung darstellen.
Und dann ist es natürlich das nächste, automatisch Änderungen zu schreiben~/.myvar
. Das wird etwas komplizierter, und ich werde an dieser Stelle aufhören, denn Umgebungsvariablen waren eigentlich nicht als Kommunikationsmechanismus zwischen den Shells gedacht, und es ist besser, einfach einen anderen Weg zu finden, dies zu tun.
Das ist dein Fehler genau dort. Sie sollten Ihre Umgebungsvariablen definieren
~/.profile
, die beim Anmelden~/.bashrc
gelesen werden. Sie werden jedes Mal gelesen, wenn Sie eine Shell starten. Wenn Sie die innere Shell starten, wird diese überschriebenMY_VAR
. Wenn Sie das nicht getan hätten, würde sich Ihre Umgebungsvariable nach unten ausbreiten.Weitere Informationen zu
~/.bashrc
vs~/.profile
finden Sie in meinen vorherigen Beiträgen zu diesem Thema .Beachten Sie, dass eine Aufwärtsausbreitung (Abrufen eines geänderten Werts aus der Subshell, der automatisch in der übergeordneten Shell widergespiegelt wird) nicht möglich ist (Punkt).
quelle
Fish Shell kann dies tun mit:
(siehe http://fishshell.com/docs/current/commands.html#set )
Um einen Fischbefehl von einer anderen Shell auszuführen
fish -c
, können Sie beispielsweise Folgendes ausführen :quelle
Verwenden Sie überhaupt keine Umgebungsvariablen. Verwenden Sie Dateien.
Verwenden Sie Sperrdateien und kleine Front-End-Updater-Skripte, um zu verhindern, dass Prozesse beim Aktualisieren / Lesen der Datei aufeinandertreffen, und aktualisieren Sie eine Datei nur mit $ 1, wenn sie nicht gesperrt ist. Sperrdateien werden implementiert, indem grundsätzlich geprüft wird, ob eine bestimmte Datei vorhanden ist (/var/run/yourscript.lck). Wenn dies der Fall ist, warten Sie, bis die Datei eine Weile verschwindet, und schlagen Sie fehl, wenn dies nicht der Fall ist. Außerdem müssen Sie die Sperrdatei löschen, wenn Sie mit dem Aktualisieren der Datei fertig sind.
Stellen Sie sich auf eine Situation ein, in der ein Skript eine Datei nicht aktualisieren kann, weil die Datei ausgelastet ist.
quelle
mkdir
als atomares Testen und Erstellen funktioniert.flock(2)
ln -s dummy lockfile
(auch wenn er defekt ist) möglicherweise auch funktioniert, da er fehlschlägt, wenn der Symlink bereits vorhanden ist. Ich frage mich, wie ich testen kann, ob das wirklich 100% sicher ist.Als ich diese Frage gerade gegoogelt habe, habe ich versucht, das Problem der Aktualisierung von Status (dh Shell-Variablen) aus Subshells heraus zu lösen. Damit man Variablen zum Beispiel innerhalb einer Pipeline zuweisen kann - und die Zuordnung für das übergeordnete Element transparent ist.
Dies ist natürlich nicht auf einfache Weise möglich, da einzelne Teile einer Pipeline in Subshells ausgeführt werden, die
fork
von der übergeordneten Shell stammen und daher über einen Speicher verfügen, der beim Schreiben kopiert werden kann. Ich nahm jedoch an, dass eine schlanke und transparente Lösung auf der Grundlage von IPCs mit " gemeinsam genutztem Speicher " möglich sein könnte .Und ich habe sogar eine Implementierung von genau diesem Design gefunden ... aber es ist in Perl.
Füge diese Antwort trotzdem als mögliche Lösung hinzu.
quelle