it-swarm.com.de

Was ist der Unterschied zwischen der Ausführung eines Bash-Skripts und der Beschaffung eines Skripts?

Was ist der Unterschied zwischen der Ausführung eines Bash-Skripts wie A und der Beschaffung eines Bash-Skripts wie B?

A
> ./myscript

B
> source myscript
263
Scottie T

Kurze Antwort

Sourcing Ein Skript führt die Befehle im Prozess currentShell aus.

Wenn Sie ausführen, werden die Befehle in einem newShell-Prozess ausgeführt.

Wenn Sie immer noch verwirrt sind, lesen Sie bitte weiter.

Terminologie

So klären Sie allgemeine Unklarheiten hinsichtlich der auszuführenden und der zu entnehmenden Syntax:

./myscript

Damit wird execute myscript ausgeführt, sofern die Datei ausführbar ist und sich im aktuellen Verzeichnis befindet. Der führende Punkt und Schrägstrich (./) kennzeichnet das aktuelle Verzeichnis. Dies ist erforderlich, da sich das aktuelle Verzeichnis normalerweise nicht in $PATH befindet (und normalerweise auch nicht sollte).

myscript

Dies führt execute myscript aus, wenn die Datei ausführbar ist und sich in einem Verzeichnis in $PATH befindet.

source myscript

Dies wird source myscript. Die Datei muss nicht ausführbar sein, es muss sich jedoch um ein gültiges Shell-Skript handeln. Die Datei kann sich im aktuellen Verzeichnis oder in einem Verzeichnis in $PATH befinden.

. myscript

Dies wird auch source myscript. Diese "Schreibweise" ist die offizielle Schreibweise im Sinne von POSIX . Bash hat source als Alias ​​für den Punkt definiert.

Demonstration

Betrachten Sie myscript.sh mit folgendem Inhalt:

#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD

Bevor wir das Skript zuerst ausführen, überprüfen wir die aktuelle Umgebung:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Die Variable FOO ist nicht definiert und wir befinden uns im Ausgangsverzeichnis.

Nun führen wir aus die Datei:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Überprüfen Sie die Umgebung erneut:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Die Variable FOO ist nicht gesetzt und das Arbeitsverzeichnis hat sich nicht geändert.

Die Skriptausgabe zeigt deutlich, dass die Variable gesetzt und das Verzeichnis geändert wurde. Die anschließende Prüfung zeigt, dass die Variable nicht gesetzt und das Verzeichnis nicht geändert wurde. Was ist passiert? Die Änderungen wurden in einer newShell vorgenommen. Aus der currentShell wurde eine newShell zum Ausführen des Skripts erstellt. Das Skript wird in der neuen Shell ausgeführt und alle Änderungen an der Umgebung werden in wirksam Die neue Shell Nachdem das Skript ausgeführt wurde, wird die neue Shell zerstört. Alle Änderungen an der Umgebung in der neuen Shell werden mit der neuen Shell zerstört. In der aktuellen Shell wird nur der Ausgabetext gedruckt.

Nun haben wir source die Datei:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Überprüfen Sie die Umgebung erneut:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

Die Variable FOO ist gesetzt und das Arbeitsverzeichnis hat sich geändert.

Durch die Beschaffung des Skripts wird keine neue Shell erstellt. Alle Befehle werden in der aktuellen Shell ausgeführt und Änderungen an der Umgebung werden in der aktuellen Shell wirksam.

Beachten Sie, dass in diesem einfachen Beispiel die Ausgabe der Ausführung der Ausgabe des Skripts entspricht. Dies ist nicht unbedingt immer der Fall.

Eine weitere Demonstration

Betrachten Sie folgendes Skript pid.sh:

#!/bin/sh
echo $$

(Die Sondervariable $$ wird auf die PID des aktuell ausgeführten Shell-Prozesses erweitert.)

Drucken Sie zuerst die PID der aktuellen Shell:

$ echo $$
25009

Quell das Skript:

$ source pid.sh
25009

Führen Sie das Skript aus und beachten Sie die PID:

$ ./pid.sh
25011

Nochmals Quelle:

$ source pid.sh
25009

Erneut ausführen:

$ ./pid.sh
25013

Sie können sehen, dass die Beschaffung des Skripts im selben Prozess ausgeführt wird, während die Ausführung des Skripts jedes Mal einen neuen Prozess erstellt. Dieser neue Prozess ist der newShell, der für die Ausführung des Skripts erstellt wurde. Durch die Beschaffung des Skripts wird keine neue Shell erstellt, und daher bleibt die PID gleich.

Zusammenfassung

Sowohl beim Aufrufen als auch beim Ausführen des Skripts werden die Befehle im Skript zeilenweise ausgeführt, als ob Sie diese Befehle von Hand zeilenweise eingegeben hätten.

Die Unterschiede sind:

  • Wenn Sie executedas Skript öffnen, das Sie newShell öffnen, geben Sie die Befehle in die neue Shell ein, kopieren Sie die Ausgabe zurück in Ihre aktuelle Shell und schließen Sie die neue Shell. Alle Änderungen an der Umgebung werden wirksam nur in der neuen Shell und geht verloren, sobald die neue Shell geschlossen wird.
  • Wenn Sie sourcedas Skript verwenden, geben Sie die Befehle in Ihre currentShell ein. Alle Änderungen an der Umgebung werden wirksam und bleiben in Ihrer aktuellen Shell.

Verwenden Sie source, wenn das Skript die Umgebung in Ihrer aktuell ausgeführten Shell ändern soll. Verwenden Sie Execute ansonsten.


Siehe auch:

327
lesmana

Das Ausführen eines Skripts führt es in einem separaten untergeordneten Prozess aus, d. H., Eine separate Instanz von Shell wird aufgerufen, um das Skript zu verarbeiten. Dies bedeutet, dass Umgebungsvariablen usw., die im Skript nicht aktualisiert werden können in der übergeordneten (aktuellen) Shell definiert sind.

Das Beschaffen eines Skripts bedeutet, dass es von der aktuellen Shell selbst analysiert und ausgeführt wird. Es ist, als ob Sie den Inhalt des Skripts eingegeben hätten. Aus diesem Grund muss das zu beschaffende Skript nicht ausführbar sein. Aber es muss ausführbar sein, wenn Sie es natürlich ausführen.

Wenn Sie in der aktuellen Shell Positionsargumente haben, bleiben diese unverändert.

Wenn ich also eine Datei a.sh habe, die enthält:

echo a $*

und ich mache:

$ set `date`
$ source ./a.sh

Ich bekomme so etwas wie:

a Fri Dec 11 07:34:17 PST 2009

Wohingegen:

$ set `date`
$ ./a.sh

gibt mir:

a

Hoffentlich hilft das.

21
Alok

das Sourcing entspricht im Wesentlichen der Eingabe jeder einzelnen Zeile des Skripts nacheinander über die Eingabeaufforderung.

Die Ausführung startet einen neuen Prozess und führt dann jede Zeile des Skripts aus. Dabei wird nur die aktuelle Umgebung anhand der zurückgegebenen Umgebung geändert.

9
John Weldon

Darüber hinaus erfordert die Ausführung des Skripts als ./myscript die Ausführungsberechtigung für die Datei myscript, während für das Sourcing keine Ausführungsberechtigung erforderlich ist. Deshalb ist chmod +x myscript nicht erforderlich, bevor source myscript

6
abs

Bei der Beschaffung erhalten Sie alle zusätzlichen Variablen, die im Skript definiert sind.
Wenn Sie also Konfigurations- oder Funktionsdefinitionen haben, sollten Sie diese als Quelle verwenden und nicht ausführen. Hinrichtungen sind unabhängig von der Umgebung der Eltern.

5
Arkaitz Jimenez

Wenn ich mich richtig erinnere, wird beim Ausführen des Skripts die ausführbare Datei in der Zeile #! mit der Skriptdatei als Argument ausgeführt (normalerweise wird eine neue Shell gestartet und das Skript wie bei #!/bin/sh effektiv in die neue Shell geladen).
wohingegen durch das Sourcing des Skripts jede Zeile in Ihrer aktuellen Shell-Umgebung ausgeführt wird. Dies ist nützlich, um Ihre aktuelle Shell zu ändern (z. B. um Shell-Funktionen zu definieren und Umgebungsvariablen zu exportieren).

3
fd

Der Befehl source führt das bereitgestellte Skript (ausführbare Berechtigung ist nicht obligatorisch in der aktuellen Shell-Umgebung aus, während ./ das bereitgestellte ausführbare Skript ausführt in einer new Shell.

Überprüfen Sie auch diese Antwort zum Beispiel: https://superuser.com/a/894748/432100

2
Harsh Vakharia