2009-12-11 15:24:17 +0000 2009-12-11 15:24:17 +0000
302
302

Was ist der Unterschied zwischen dem Ausführen eines Bash-Skripts und dem Sourcen eines Skripts?

Was ist der Unterschied zwischen dem Ausführen eines Bash-Skripts wie A und dem Sourcen eines Bash-Skripts wie B?

A
> ./myscript

B
> source myscript

Antworten (6)

369
369
369
2010-08-16 21:58:48 +0000

Ein Skript ausgeben führt die Befehle im aktuellen Shell-Prozess aus.

Ausführen eines Skripts führt die Befehle in einem neuen Shell-Prozess aus.

Verwenden Sie source, wenn das Skript die Umgebung in Ihrer aktuell laufenden Shell ändern soll. verwenden Sie andernfalls execute.

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

Terminologie

Um einige häufige Verwirrungen über die Syntax für execute und die Syntax für source zu klären:

./myscript

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

myscript

Damit wird myscript ausgeführt, wenn die Datei ausführbar ist und sich in einem Verzeichnis in $PATH befindet.

source myscript

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

. myscript

Dies wird auch Quelle myscript. Diese “Schreibweise” ist die offizielle, wie sie von POSIX definiert ist. Die 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 ausführen, überprüfen wir zunächst die aktuelle Umgebung:

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

Die Variable FOO ist nicht definiert und wir befinden uns im Home-Verzeichnis.

Nun ausführen wir 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 wurde und das Verzeichnis gewechselt wurde. Die Prüfung danach zeigt, dass die Variable nicht gesetzt und das Verzeichnis nicht geändert wurde. Was ist passiert? Die Änderungen wurden in einer neuen Shell vorgenommen. Die aktuelle Shell hat eine neue Shell erzeugt, um das Skript auszuführen. Das Skript wird in der neuen Shell ausgeführt und alle Änderungen an der Umgebung werden in der neuen Shell wirksam. Nachdem das Skript fertig ist, wird die neue Shell zerstört. Alle Änderungen an der Umgebung in der neuen Shell werden mit der neuen Shell zerstört. Nur der Ausgabetext wird in der aktuellen Shell ausgegeben.

Jetzt sourcen wir 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.

Beim Aufruf 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 des Ausführens die gleiche ist wie das Auslagern des Skripts. Dies ist nicht unbedingt immer der Fall.

Eine weitere Demonstration

Betrachten Sie folgendes Skript pid.sh:

#!/bin/sh
echo $$

(die spezielle Variable $$ expandiert zur PID des aktuell laufenden Shell-Prozesses)

Zuerst die PID der aktuellen Shell ausgeben:

$ echo $$
25009

Das Skript sourcen:

$ source pid.sh
25009

Führen Sie das Skript aus, notieren Sie die PID:

$ ./pid.sh
25011

Erneut Sourcen:

$ source pid.sh
25009

Erneut Ausführen:

$ ./pid.sh
25013

Sie sehen, dass das Sourcen des Skripts im selben Prozess läuft, während das Ausführen des Skripts jedes Mal einen neuen Prozess erzeugt. Dieser neue Prozess ist die neue Shell, die für die Ausführung des Skripts erstellt wurde. Durch das Auslagern des Skripts wird keine neue Shell erstellt und somit bleibt die PID gleich.

Zusammenfassung

Sowohl bei der Beschaffung als auch bei der Ausführung des Skripts werden die Befehle im Skript Zeile für Zeile ausgeführt, als ob Sie diese Befehle Zeile für Zeile von Hand eingeben würden.

Die Unterschiede sind:

  • Wenn Sie das Skript ausführen, öffnen Sie eine neue Shell, geben die Befehle in die neue Shell ein, kopieren die Ausgabe zurück in Ihre aktuelle Shell und schließen dann die neue Shell. Alle Änderungen an der Umgebung werden nur in der neuen Shell wirksam und gehen verloren, sobald die neue Shell geschlossen wird.
  • Wenn Sie das Skript sourcen, geben Sie die Befehle in Ihrer aktuellen Shell ein. Alle Änderungen an der Umgebung werden wirksam und bleiben in Ihrer aktuellen Shell erhalten.

Verwenden Sie source, wenn Sie möchten, dass das Skript die Umgebung in Ihrer aktuellen Shell ändert. verwenden Sie ansonsten execute.


Siehe auch:

23
23
23
2009-12-11 15:35:56 +0000

Wenn Sie ein Skript ausführen, wird es in einem separaten untergeordneten Prozess ausgeführt, d. h. es wird eine separate Instanz der Shell aufgerufen, um das Skript zu verarbeiten. Das bedeutet, dass alle Umgebungsvariablen usw., die im Skript definiert sind, in der übergeordneten (aktuellen) Shell nicht aktualisiert werden können.

Ein Skript auszuliefern bedeutet, dass es von der aktuellen Shell selbst geparst und ausgeführt wird. Es ist so, als ob Sie den Inhalt des Skripts eintippen würden. Aus diesem Grund muss das Skript, das gesourced wird, nicht ausführbar sein. Aber es muss natürlich ausführbar sein, wenn Sie es ausführen wollen.

Wenn Sie Positionsargumente in der aktuellen Shell 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

erhalte ich etwas wie:

a Fri Dec 11 07:34:17 PST 2009

dagegen:

$ set `date`
$ ./a.sh

liefert mir:

a

Hoffentlich hilft das.

9
9
9
2009-12-11 15:27:08 +0000

sourcing ist im Wesentlichen dasselbe wie das Eintippen jeder Zeile des Skripts an der Eingabeaufforderung, eine nach der anderen…

Die Ausführung startet einen neuen Prozess und führt dann jede Zeile des Skripts aus, wobei die aktuelle Umgebung nur durch das verändert wird, was sie zurückgibt.

6
6
6
2012-02-23 07:27:43 +0000

Zusätzlich zu den obigen Ausführungen erfordert die Ausführung des Skripts als ./myscript die Ausführungsberechtigung für die Datei myscript, während für das Sourcen keine Ausführungsberechtigung erforderlich ist. Deshalb wird chmod +x myscript nicht vor source myscript benötigt.

5
5
5
2009-12-11 15:25:38 +0000

Beim Sourcen erhalten Sie alle zusätzlichen Variablen, die im Skript definiert sind.
Wenn Sie also Configs oder Funktionsdefinitionen haben, sollten Sie quellen und nicht ausführen. Ausführen ist unabhängig von der übergeordneten Umgebung.

2
2
2
2015-03-27 14:04:20 +0000

Der Befehl source führt das angegebene Skript (Ausführungserlaubnis ist nicht zwingend ) in der aktuellen Shell-Umgebung aus, während ./ das angegebene ausführbare Skript in einer neuen Shell ausführt.

Sehen Sie sich auch diese Antwort als Beispiel an: https://superuser.com/a/894748/432100