
Ich habe 2 Shell-Skripte, file1.sh und file2.sh
datei1.sh
#!/usr/bin/env bash
export var1="/data/share"
export var2='password'
echo "Hello"
file2.sh
#!/usr/bin/env bash
source file1.sh
echo $var1
echo $var2
Wenn ich file2.sh ausführe, erhalte ich die folgende Ausgabe
Hello
/data/share
password
Aber mein erwartetes Ergebnis ist
/data/share
password
file1.sh wird ausgeführt, wenn in file2.sh darauf verwiesen wird. Wie importiere ich die Variablen allein in file2.sh, ohne file1.sh auszuführen?
Antwort1
Es gibt drei Optionen, die ich verwende, wenn ich ein Bash-Skript habe, das sich beim Aufrufen anders verhalten soll als beim Ausführen (oder mit anderen Worten, wenn ich Datenelemente in einem Skript habe, auf die ich zugreifen möchte, ohne zu diesem Zeitpunkt Code auszuführen). Die Kommentare haben diese bis zu einem gewissen Grad angesprochen.
Option eins
Bestimmen Sie, wann beschafft wird, und beenden Sie die Beschaffung zum geeigneten Zeitpunkt
Teilen Sie das Skript in zwei Abschnitte auf und beenden Sie es, wenn die Quelle angegeben wird, bevor Sie zur unteren zweiten Zeile gelangen.
Erstellen Sie einen oberen Skriptabschnitt mit Definitionen (Funktionen/Variablenzuweisungen usw.), aber ohne direkte Codeausführung.
Direkt vor dem Beginn des ausführbaren Codeabschnitts platzieren Sie eine Logik, die das Skript beendet, wenn es erkennt, dass es als Quelle verwendet wird. Das folgende Codesegment tut dies:
datei1.sh
#!/usr/bin/env bash
export var1="/data/share"
export var2='password'
# --- End Definitions Section ---
# check if we are being sourced by another script or shell
[[ "${#BASH_SOURCE[@]}" -gt "1" ]] && { return 0; }
# --- Begin Code Execution Section ---
echo "Hello"
echo $var1
echo $var2
file2.sh
#!/usr/bin/env bash
source file1.sh
echo "$var1"
echo "$var2"
Ausgabe der Ausführung von ./file2.sh
$ ./file2.sh
/data/share
password
Option Zwei
Dieser Modus wird normalerweise nur in komplexen Situationen verwendet und ist für dieses spezielle Beispiel übertrieben. Ich erstelle eine Funktion in der Datei, die ich als Quelle verwenden möchte, und bestimme in dieser Funktion, was dem Anrufer zur Verfügung stehen soll. In diesem Fall sind es die beiden exportierten Variablen. Normalerweise verwende ich diesen Modus, wenn ich assoziative Arrays habe, die sonst kaum zu übergeben sind. Außerdem sollte die temporäre Datei vom Anrufer gelöscht werden; in diesem Fall habe ich das jedoch nicht getan:
datei1.sh
#!/usr/bin/env bash
export var1="/data/share"
export var2='password'
exportCfg() {
tmpF=$(mktemp)
declare -p var1 var2 > "$tmpF"
echo "$tmpF"
}
if [ "$1" == "export" ]; then
exportCfg;
exit 0;
fi
echo "Hello"
echo $var1
echo $var2
file2.sh
#!/usr/bin/env bash
source $(./file1.sh export)
echo "$var1"
echo "$var2"
Die Ausgabe der Ausführung von file2.sh ist die gleiche wie oben
Option 3
Die letzte übliche Methode, mit der ich das handhabe, ist einfach eine Bibliotheksdatei, die nur Definitionen enthält und keinen Code hat, der ausgeführt wird, wenn er bezogen oder direkt ausgeführt wird. Dabei geht es einfach darum, Ihren Code aufzuteilen. Ich habe eine Gruppe von Bash-Bibliotheken, die häufig verwendete Funktionen enthalten, und richte normalerweise pro Projekt eine kleine ausführbare Bibliothek zum Speichern von Konfigurationsdaten (Konstanten) ein. Wenn diese Daten ausgefüllte Arrays enthalten, verwende ich auch eine Version von Option 2.
Antwort2
Wenn Ihre Variablen alle auf die gleiche Weise exportiert werden (exportiere foo=bar), dann können Sie sie alle ganz einfach beziehen mitSchlagProzesssubstitutionsfunktion:
source <(grep '^export .*=' file1.sh)
Auszug aus der Manpage:
Prozessersetzung Prozessersetzung wird auf Systemen unterstützt, die benannte Pipes (FIFOs) oder die /dev/fd-Methode zum Benennen offener Dateien unterstützen. Sie hat die Form <(Liste) oder >(Liste). Der Prozess Liste wird mit seiner Eingabe oder Ausgabe ausgeführt, die mit einer FIFO oder einer Datei in /dev/fd verbunden ist. Der Name dieser Datei wird als Ergebnis der Erweiterung als Argument an den aktuellen Befehl übergeben. Wenn die Form >(Liste) verwendet wird, liefert das Schreiben in die Datei eine Eingabe für die Liste. Wenn die Form <(Liste) verwendet wird, sollte die als Argument übergebene Datei gelesen werden, um die Ausgabe der Liste zu erhalten.