GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Was ist der Unterschied zwischen der Verwendung von „sh“ und „source“?

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.;-)


Linux
  1. Der Unterschied zwischen [[ $a ==Z* ]] und [ $a ==Z* ]?

  2. Was ist der Unterschied zwischen insmod und modprobe

  3. Was ist der Unterschied zwischen strtok_r und strtok_s in C?

  4. Was ist der Unterschied zwischen fsck und e2fsck?

  5. Was ist der Unterschied zwischen ls und l?

Was ist der Unterschied zwischen Linux und Unix?

Was ist der Unterschied zwischen Login- und Non-Login-Shell

Was ist der Unterschied zwischen apt und dem Befehl apt-get?

Was ist ein Hypervisor? Was ist der Unterschied zwischen Typ 1 und 2?

Was ist der Unterschied zwischen Curl und Wget?

Was ist der Unterschied zwischen Route und IP-Route?