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

283

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
Scottie T
quelle
Sie könnten dies lesen: bash.cyberciti.biz/guide/Source_command
ERU

Antworten:

345

Kurze Antwort

Durch die Beschaffung eines Skripts werden die Befehle im aktuellen Shell-Prozess ausgeführt.

Durch Ausführen eines Skripts werden die Befehle in einem neuen Shell-Prozess ausgeführt.

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

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

Terminologie

Um einige allgemeine Unklarheiten über die auszuführende Syntax und die zu quellende Syntax zu klären:

./myscript

Dies wird ausgeführt, myscript 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 notwendig, da das aktuelle Verzeichnis normalerweise nicht in ist (und normalerweise nicht sein sollte) $PATH.

myscript

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

source myscript

Dies wird Quelle 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 befinden $PATH.

. myscript

Dies wird auch Quelle myscript . Diese "Schreibweise" ist die offizielle, wie sie von POSIX definiert wurde . Bash wird sourceals Alias ​​für den Punkt definiert.

Demonstration

Bedenken Sie myscript.shmit 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 FOOist nicht definiert und wir befinden uns im Home-Verzeichnis.

Jetzt sind 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 FOOist 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 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. Nach Abschluss des Skripts 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 wir beziehen 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 Spezialvariable 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 die neue Shell, die 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 das Skript ausführen, öffnen Sie eine neue Shell, 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. Änderungen an der Umgebung werden nur in der neuen Shell wirksam und gehen verloren, sobald die neue Shell geschlossen wird.
  • Wenn Sie das Skript als Quelle angeben, geben Sie die Befehle in Ihre aktuelle Shell 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:

lesmana
quelle
2
Eine Verwendung von Sourcing ist das Erstellen einer rudimentären Konfigurationsdatei für Ihre Skripte. Sie beginnen damit, verschiedene Variablen auf Standardwerte zu setzen und dann in so etwas wie myscript.conf zu quellen - und dieses Quellenskript kann Zuweisungsanweisungen enthalten, die die von Ihnen gewünschten Werte überschreiben. Da das Quellenskript nicht mit # / bin / bash beginnt, wird es nicht dazu aufgefordert, es direkt auszuführen.
LawrenceC
Source ist also so etwas wie das Ausführen in einem globalen Bereich, und das Ausführen erstellt einen neuen lokalen Bereich. Kann dies auf eine Funktion in einem Skript erweitert werden? eine funktion (normal) ausführen oder "quellen"?
Aliteralmind
2
Gibt es einen Unterschied zwischen der Verwendung von source myscript.shund . myscript.sh?
Holloway
2
praktisch kein unterschied bei der verwendung von bash. source ist ein Alias ​​für bash.
Lesmana
1
Ich finde es toll, wenn Leute so aufwändige Beispiele liefern, dass selbst Linux-Neulinge wie ich es verstehen können. Vielen Dank!
Julius
21

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

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.

Also, wenn ich eine Datei habe, die a.shenthä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

Ich hoffe, das hilft.

Alok
quelle
5
Obwohl diese Antwort in jeder Hinsicht richtig ist, fällt es mir schwer, sie zu verstehen, da sie anhand eines anderen Konzepts (Einstellen von Positionsparametern) demonstriert wird, das meiner Meinung nach noch verwirrender ist als der Unterschied zwischen Beschaffung und Ausführung.
Lesmana
9

Sourcing ist im Wesentlichen dasselbe wie das Eingeben jeder einzelnen Zeile des Skripts an der 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.

John Weldon
quelle
6

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

Abs
quelle
2
Stimmt, aber wenn das ein Problem ist, können Sie immer laufen bash myscript.
Daniel Beck
5

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. Die Hinrichtungen sind unabhängig von der Umgebung der Eltern.

Arkaitz Jimenez
quelle
3

Wenn ich mich wieder 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 wird wie bei "" in die neue Shell geladen #!/bin/sh).
Durch die Verwendung des Skripts wird jede Zeile in Ihrer aktuellen Shell-Umgebung ausgeführt. Dies ist nützlich, um Ihre aktuelle Shell zu ändern (z. B. um Shell-Funktionen zu definieren und Umgebungsvariablen zu exportieren).

Shekhar
quelle
2

sourceDer Befehl führt das bereitgestellte Skript in der aktuellen Shell-Umgebung aus (ausführbare Berechtigungen sind nicht erforderlich ) , während das bereitgestellte ausführbare Skript in einer neuen Shell ausgeführt wird../

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

Harte Vakharia
quelle