Erfassen Sie spezifische Umgebungsvariablen von der Linux-Sub-Shell

853
NerdPirate

Ich versuche, einen Weg zu finden, ein Shell-Skript B aus Skript A auszuführen, eine Variable in Skript B festzulegen oder zu exportieren und diesen Wert in Skript A zu speichern, nachdem das Skript B beendet ist und die Sub-Shell zurückgegeben wird.

Ich versuche nicht, das Skript B zu beziehen. Ich möchte nur eine bestimmte Variable. Ich kann dem Skript A Sachen hinzufügen, aber ich möchte nicht, dass Variablen, die möglicherweise in Skript B gesetzt sind, in Skript A etwas überschreiben, außer dem, was ich speziell zu erfassen versuche.

Ich bin sicher, dass es einige hässliche Möglichkeiten gibt, z. B. alle Variablen, die mich in A interessieren, in eine Datei zu schreiben (Quellskript B), dann alles wieder in die Datei zu lesen und die Variablen in A wiederherzustellen, außer der in B eingestellten Variablen das ich möchte. Ich suche nach einem relativ sauberen und unkomplizierten Weg, falls vorhanden.

2
"Ich möchte nicht, dass Variablen, die möglicherweise in Skript B festgelegt wurden, etwas in Skript A außer dem überschreiben, was ich speziell erfassen möchte" - Variablen, die in Skript B (in einer Subshell) festgelegt sind, überschreiben keine Variablen in A. Kind Prozesse können nicht in die Umgebungsvariablen ihres übergeordneten Prozesses schreiben. Sie müssen sie speziell erfassen. Roger Lipscombe vor 5 Jahren 0
Genau ... das möchte ich tun. Ich möchte sie spezifisch einfangen, wie im Titel meiner Frage. Meine Aussage sollte Vorschläge des Sourcing-Skripts B unterbinden. NerdPirate vor 5 Jahren 0

2 Antworten auf die Frage

5
Ipor Sircer

Schreibe diese spezifische Variable in stdout und dann in A:

specificvariable=$(/path/to/B.sh) 
Upvoted, wenige Notizen (meistens jedoch für unerfahrene Benutzer): (1) Hier wird "B.sh" ausgeführt. Sie müssen also den gesamten Befehl anstelle von "B.sh" ausführen, nicht zusätzlich. (2) Dadurch wird die gesamte Ausgabe von "B.sh" erfasst. Wenn das Skript mehr als die gewünschte Variable schreibt, kann die Lösung nicht einfach angewendet werden. // Wenn Sie möchten, können Sie meine Anmerkungen als Ihre eigenen in die Antwort aufnehmen (dh ohne meine Eingabe zu erwähnen); Ich denke, das würde die Antwort noch besser machen. Kamil Maciorowski vor 5 Jahren 3
Dies ist eine gute Option, jedoch nicht für meinen Anwendungsfall, da B.sh möglicherweise andere Ausgaben ausgibt. Dies ist jedoch eine gute Antwort für andere Menschen, die sich dieser Frage stellen. Vielen Dank NerdPirate vor 5 Jahren 0
3
Kamil Maciorowski

Diese andere Antwort ist gut, sie sollte Ihre erste Wahl sein, besonders wenn Ihr B-Skript eine Sache tut und es gut macht (siehe Unix-Philosophie ) und diese "eine Sache" bedeutet "diesen bestimmten Variablenwert berechnen".

Was aber, wenn der Hauptzweck von B darin besteht, etwas anderes zu drucken? oder sogar mit dem Benutzer interagieren? Die Weitergabe zusätzlicher Daten über stdout erfordert eine zusätzliche Analyse des abgerufenen Ergebnisses. Wenn ja, ist ein völlig unabhängiger Kommunikationskanal zwischen B und A sehr erwünscht. In Ihrem Fall ist Kommunikation in eine Richtung ausreichend.

Eine temporäre Datei ist tatsächlich gut für sie. Aber wenn du sagst

Hässliche Wege, wie das Schreiben aller Variablen, die ich in A interessiert, in eine Datei (Quellskript B), dann alles wieder in die Datei einlesen und die Variablen in A wiederherstellen, außer der in B gesetzten Variablen, die ich möchte

Sie stellen die Situation auf den Kopf und es ist in der Tat hässlich. Der richtige Weg ist, eine Datei zu verwenden, um nur diese eine gewünschte Variable zu übergeben.

In einem:

tmpf_foo=$(mktemp) 

Dann rufen Sie B mit "$tmpf_foo"als Befehlszeilenargument auf und beziehen sich auf die Datei "$1"in B (oder, abhängig vom Design, unter einer anderen Nummer). Dies ist möglicherweise nicht sinnvoll, wenn B seine Befehlszeilenargumente bereits analysiert.

Ein alternativer Weg ist export tmpf_fooin A und auf die Datei wie "$tmpf_foo"in B zu verweisen .

Wenn B ein Universalwerkzeug ist, das nicht nur von A aus verwendet werden kann, sollten Sie (in B) prüfen, ob die Datei vorhanden ist, bevor Sie darauf schreiben (z if [ -f "$tmpf_foo" ]; then …. B. ).

Jedenfalls schreiben Sie in B den gewünschten Wert in die Datei. Zum Beispiel wird der Inhalt der Datei sein:

12345 

Nachdem B erfolgreich abgeschlossen wurde, rufen Sie in A den folgenden Wert ab:

specificvariable=$(<"$tmpf_foo") 

(Äquivalent zu specificvariable=$(cat "$tmpf_foo")aber ohne cat; obwohl nicht tragbar).

Wenn Sie mehr als eine Variable von B nach A übergeben müssen, können Sie mehrere Zeilen verwenden und diese mit (in A) lesen read. Wenn Sie jedoch nicht im Voraus wissen, welche Variablen geändert werden sollen (oder ob überhaupt), erstellen Sie B, um Zeilen in der Datei zu erstellen, sodass es so aussieht:

specificvariable=12345 othervariable="xyz 0" bar=baz unset var1 

Nachdem B erfolgreich abgeschlossen wurde, geben Sie in A die Datei ein:

. "$tmpf_foo" 

Beachten Sie, dass Sie jeden Befehl auf diese Weise übergeben können (im obigen Beispiel unsethandelt es sich um einen Befehl), und er wird von A ausgeführt. Aus diesem Grund sollten Sie beim Schreiben in die Datei aus B sehr vorsichtig sein, und Sie sollten sicherstellen, dass kein anderer ( Rogue) kann Strings in die Datei einfügen.

Am Ende (in A) entfernen Sie die temporäre Datei mit rm "$tmpf_foo".

Oh das gefällt mir. Der Export einer temporären Datei passt gut zu meinem Anwendungsfall. Vielen Dank! NerdPirate vor 5 Jahren 0