Frage Was ist der Unterschied zwischen der Ausführung eines Bash-Skripts und dem Sourcing?


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

213
2017-12-11 15:24


Ursprung




Antworten:


Kurze Antwort: Sourcing führt die Befehle im aktuellen Shell-Prozess aus. Beim Ausführen werden die Befehle in einem neuen Shell-Prozess ausgeführt. immer noch verwirrt? dann lesen Sie bitte weiter die lange Antwort.

Terminologie:

Um einige allgemeine Unklarheiten über die auszuführende Syntax und die Quellsyntax zu verdeutlichen:

./myscript

Ausführen  myscript vorausgesetzt, dass die Datei ausführbar ist und sich im aktuellen Verzeichnis befindet. Der führende Punktstrich (./) bezeichnet das aktuelle Verzeichnis. Dies ist notwendig, da das aktuelle Verzeichnis normalerweise nicht in ist $PATH.

myscript

Ausführen  myscript wenn die Datei ausführbar ist und sich in einem Verzeichnis in befindet $PATH.

source myscript

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

. myscript

Quelle  myscript. Diese Syntax ist definiert durch POSIX. Bash definiert source als Alias ​​für den Punktbefehl.

Demonstration:

Erwägen 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 sind im Home-Verzeichnis.

Jetzt wir ausführen 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 festgelegt und das Arbeitsverzeichnis hat sich nicht geändert.

Die Skriptausgabe zeigt deutlich, dass die Variable gesetzt wurde und das Verzeichnis geändert wurde. Der anschließende Check zeigt, dass die Variable nicht gesetzt ist und das Verzeichnis nicht geändert wurde. Was ist passiert? Die Änderungen wurden in a gemacht Neu Schale. Das Strom Shell brachte ein Neu Shell, 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 gedruckt.

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

Das Sourcing des Skripts erstellt keine neue Shell. 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 von Ausführen dasselbe ist wie das Sourcing des Skripts. Dies ist nicht immer der Fall.

Eine weitere Demonstration:

Überlege dir folgendes Skript pid.sh:

#!/bin/sh
echo $$

(die spezielle Variable $$ expandiert auf die PID des aktuellen laufenden Shell-Prozesses)

Drucken Sie zuerst die PID der aktuellen Shell:

$ echo $$
25009

Quelle das Skript:

$ source pid.sh
25009

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

$ ./pid.sh
25011

Quelle noch einmal:

$ source pid.sh
25009

Nochmals ausführen:

$ ./pid.sh
25013

Sie können sehen, dass das Sourcing des Scripts während der Ausführung des Scripts im selben Prozess ausgeführt wird und dass jedes Mal ein neuer Prozess erstellt wird. Dieser neue Prozess ist der Neu Shell, die für die Ausführung des Skripts erstellt wurde. Das Sourcing des Skripts erstellt keine neue Shell und somit bleibt die PID gleich.

Zusammenfassung

Sowohl das Sourcing als auch das Ausführen des Skripts führt die Befehle im Skript Zeile für Zeile aus, so als ob Sie diese Befehle Zeile für Zeile manuell eingegeben hätten.

Die Unterschiede sind:

  • Wenn du ausführen das Skript, das Sie öffnen Neu Geben Sie die Befehle in der neuen Shell ein, kopieren Sie die Ausgabe zurück in Ihre aktuelle Shell und schließen Sie 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 du Quelle das Skript, in das Sie die Befehle in Ihrem eingeben Strom Schale. Alle Änderungen an der Umgebung werden wirksam und verbleiben in Ihrer aktuellen Shell.

Verwenden Sie die Quelle, wenn das Skript die Umgebung in der aktuell ausgeführten Shell ändern soll. Verwenden Sie andernfalls Ausführen.


Siehe auch:


277
2017-08-16 21:58



Eine Verwendung von Sourcing erstellt eine rudimentäre Form der Konfigurationsdatei für Ihre Skripte. Sie beginnen damit, dass Sie verschiedene Variablen auf die Standardwerte setzen und dann etwas wie myscript.conf eingeben - und dieses Quellskript kann Zuweisungsanweisungen haben, die alle gewünschten Werte überschreiben. Da das Quellskript nicht mit # / bin / bash beginnt, wird es nicht empfohlen, es direkt auszuführen. - LawrenceC
So ist Source so, als ob sie in einem globalen Bereich ausgeführt wird, und die Ausführung erstellt einen neuen lokalen Bereich. Kann dies zu einer Funktion in einem Skript erweitert werden? um eine Funktion (normalerweise) auszuführen oder sie "zu quellen"? - aliteralmind
Das Aufrufen einer Shell-Funktion verhält sich normalerweise ähnlich wie das Sourcing. das Aufrufen einer Shell-Funktion innerhalb einer Subshell verhält sich ähnlich wie das Ausführen. - lesmana
Gibt es einen Unterschied zwischen der Verwendung? source myscript.sh und . myscript.sh? - Holloway
Praktisch kein Unterschied bei bash. source ist ein Alias ​​für den Punkt in bash. - lesmana


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

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

Wenn Sie Positionsargumente in der aktuellen Shell haben, sind sie unverändert.

Also wenn ich eine Datei habe a.sh enthält:

echo a $*

und ich mache:

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

Ich bekomme etwas wie:

a Fri Dec 11 07:34:17 PST 2009

Wohingegen:

$ set `date`
$ ./a.sh

gibt mir:

a

Ich hoffe, das hilft.


21
2017-12-11 15:35



Obwohl diese Antwort in jeder Hinsicht korrekt ist, finde ich sie sehr schwer zu verstehen, weil sie mit einem anderen Konzept demonstriert wird (Einstellung von Positionsparametern), was meines Erachtens noch verwirrender ist als der Unterschied zwischen Beschaffung und Ausführung. - lesmana


Sourcing ist im Wesentlichen das Gleiche wie das Eingeben jeder Zeile des Skripts an der Eingabeaufforderung nacheinander ...

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


5
2017-12-11 15:27





Sourcing Sie erhalten alle zusätzlichen Variablen im Skript definiert.
Also, wenn Sie Configs oder Funktionsdefinitionen haben, sollten Sie Quelle und nicht ausführen. Ausführungen sind unabhängig von der Umgebung der Eltern.


4
2017-12-11 15:25





Zusätzlich zu oben, Ausführen des Skripts als ./myscript erfordert die Berechtigung zum Ausführen der Datei myscript, während das Sourcing keine Ausführungsberechtigung erfordert. Deswegen chmod +x myscript ist vorher nicht erforderlich source myscript


4
2018-02-23 07:27



Stimmt, aber wenn das ein Problem ist, können Sie immer laufen bash myscript. - Daniel Beck♦


Wenn ich mich richtig erinnere, führt die Ausführung des Skripts die ausführbare Datei in der #! Linie mit der Skriptdatei als ein Argument (in der Regel eine neue Shell starten und effektiv das Skript in die neue Shell, wie mit #!/bin/sh);
während das Sourcing des Skripts jede Zeile in Ihrer aktuellen Shell-Umgebung ausführt, was nützlich ist, um Ihre aktuelle Shell zu verändern (zum Beispiel, um Shell-Funktionen zu definieren und Umgebungsvariablen zu exportieren).


3
2017-12-11 15:27





source Befehl führt das bereitgestellte Skript aus (ausführbare Erlaubnis ist nicht verpflichtend) in dem Strom Shell-Umgebung, während ./ führt das zur Verfügung gestellte aus ausführbar Skript in einem Neu Schale.

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


2
2018-03-27 14:04