Hlavním rozdílem je, že jsou prováděny v jiném procesu.
Pokud tedy source
soubor foo
což dělá cd
, je ovlivněn zdrojový shell (např. váš interaktivní shell v terminálu) (a jeho aktuální adresář se změní)
Pokud spustíte sh foo
cd
neovlivňuje zdrojový shell, pouze čerstvě vytvořený sh
proces běží foo
Přečtěte si Advanced Bash Scripting Guide.
Jak již uvedli ostatní, když spustíte sh test.sh
, všechny změny, které test.sh
udělá do vašeho prostředí shellu nebude po ukončení procesu přetrvávat.
Pamatujte však také, že jakýkoli prvek vašeho prostředí, který není exportován (např. proměnné, aliasy a funkce shellu), nebude pro kód v test.sh
dostupný. když je spuštěn jako podproces (tj. s sh test.sh
).
Například:
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
Příklad 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$
Když zavoláte na source
nebo .
(jeden je alias druhého. source
cmd ne POSIX – druh bashismu ), načtete a spustíte skript shellu do aktuálního skořápkový proces . Takže můžete
- čte proměnné nastavené ve zdrojovém skriptu,
- použijte v něm definované funkce.
- a dokonce spustit rozvětvení a/nebo podproces, pokud to skript provede.
Když zavoláte na sh
, spustíte fork (dílčí proces nebo dítě ), která spustí novou relaci /bin/sh
(což je často symbolický odkaz na bash
). V tomto případě by proměnné prostředí nastavené dolním indexem byly zrušeny, když se dolní index ukončí.
Pozor :sh
může být symbolický odkaz na jinou shell.
Praktický příklad
Například pokud chcete změnit aktuální pracovní adresář konkrétním způsobem byste to nemohli udělat
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
To nebude dělat to, co očekáváte:
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
protože aktuální pracovní adresář je součástí prostředí a myCd2Doc.sh
by běžel v subshell .
Ale:
$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
Podívejte se na mycd
funkce!! (S dokončením bash na základě Asociativního pole ).
Úroveň provedení $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.
Rekurze (když skript běží sám od sebe)
$ 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.
O něco dále
$ 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
( Aktuální PID ($$
==ID procesu ) mají stejný identifikátor než SID (ID relace ). Není to vždy pravda.)
$ ./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
Tečka .
je alias source
. Takže jediný rozdíl mezi dvěma příkazy je slash
nahrazeno space
.
A finále test:
$ 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.
... Můžete si všimnout jiného chování mezi dvěma syntaxemi.;-)