Der Hauptunterschied besteht darin, dass sie in einem anderen Prozess ausgeführt werden.
Wenn Sie also source
eine Datei foo
was einen cd
macht , die Sourcing-Shell (z. B. Ihre interaktive Shell im Terminal) ist betroffen (und ihr aktuelles Verzeichnis ändert sich)
Wenn Sie sh foo
ausführen die cd
wirkt sich nicht auf die Sourcing-Shell aus, sondern nur auf den frisch erstellten sh
Prozess, der foo
ausführt
Lesen Sie den Advanced Bash Scripting Guide.
Wie andere bereits erwähnt haben, wenn Sie sh test.sh
ausführen , alle Änderungen, die test.sh
Makes in Ihrer Shell-Umgebung bleiben nach Beendigung des Prozesses nicht bestehen.
Beachten Sie jedoch auch, dass alle Elemente Ihrer Umgebung, die nicht exportiert werden (z. B. Variablen, Aliase und Shell-Funktionen), für den Code in test.sh
nicht verfügbar sind wenn es als Unterprozess ausgeführt wird (also mit sh test.sh
).
Zum Beispiel:
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
Beispiel 2:
[email protected]:~$ cat test.sh
#!/bin/sh
cd /etc
[email protected]:~$ sh test.sh
[email protected]:~$ pwd
/home/savoury
[email protected]:~$ source test.sh
[email protected]:/etc$ pwd
/etc
[email protected]:/etc$
Wenn Sie source
anrufen oder .
(das eine ist ein Alias für das andere. source
cmd nicht POSIX - eine Art Bashismus ), laden Sie ein Shell-Skript in die aktuelle und führen es aus Shell-Prozess . Sie können also
- Variablen lesen, die im Quellskript gesetzt sind,
- darin definierte Funktionen verwenden.
- und sogar Forks und/oder Unterprozesse ausführen, wenn das Skript dies tut.
Wenn Sie sh
anrufen , initiieren Sie einen Fork (Unterprozess oder Kind ), die eine neue Sitzung von /bin/sh
ausführt (was oft ein symbolischer Link zu bash
ist ). In diesem Fall würden die vom Unterskript gesetzten Umgebungsvariablen gelöscht, wenn das Unterskript beendet wird.
Achtung :sh
könnte ein symbolischer Link zu einem anderen sein Schale.
Praxisbeispiel
Zum Beispiel, wenn Sie das aktuelle Arbeitsverzeichnis ändern möchten auf eine bestimmte Art und Weise nicht
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
Dies wird nicht das tun, was Sie erwarten:
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
weil aktuelles Arbeitsverzeichnis ist Teil der Umgebung und myCd2Doc.sh
würde in einer Subshell laufen .
Aber:
$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
Sehen Sie sich mycd
an Funktion!! (Mit Bash-Vervollständigung basierend auf Associative Array ).
Ausführungsebene $SHLVL
$ cd /tmp
printf %b '\43\41/bin/bash\necho This is level \44SHLVL.\n' >qlvl.sh
$ bash qlvl.sh
This is level 2.
$ source qlvl.sh
This is level 1.
Rekursion (wenn ein Skript von sich selbst ausgeführt wird)
$ cat <<eoqlvl2 >qlvl2.sh
#!/bin/bash
export startLevel recursionLimit=5
echo This is level $SHLVL started:${startLevel:=$SHLVL}.
(( SHLVL < recursionLimit )) && ./qlvl2.sh
eoqlvl2
$ chmod +x qlvl2.sh
$ ./qlvl2.sh
This is level 2 started:2.
This is level 3 started:2.
This is level 4 started:2.
This is level 5 started:2.
$ source qlv2.sh
This is level 1 started:1.
This is level 2 started:1.
This is level 3 started:1.
This is level 4 started:1.
This is level 5 started:1.
Ein bisschen weiter
$ sed '$a ps --sid $SID fw' qlvl.sh >qlvl3.sh
$ chmod +x qlvl3.sh
$ export SID
$ read SID < <(ps ho sid $$)
$ echo $SID $$
8983 8983
( Aktuelle PID ($$
==Prozess-ID ) sind dieselben Kennungen wie SID (Sitzungs-ID ). Es ist nicht immer wahr.)
$ ./qlvl3.sh
This is level 2.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10266 pts/10 S+ 0:00 \_ /bin/bash ./qlvl3.sh
10267 pts/10 R+ 0:00 \_ ps --sid 8983 fw
$ . qlvl3.sh
This is level 1.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10428 pts/10 R+ 0:00 \_ ps --sid 8983 fw
Punkt .
ist ein Alias von source
. Der einzige Unterschied zwischen zwei Befehlen ist also slash
ersetzt durch space
.
Und ein Finale testen:
$ printf %b '\43\41/bin/bash\necho Ending this.\nsle' \
'ep 1;exit 0\n' >finalTest.sh
$ bash finalTest.sh
Ending this.
$ source finalTest.sh
Ending this.
... Sie werden vielleicht einen anderen bemerken Verhalten zwischen den beiden Syntaxen.;-)