GNU/Linux >> Znalost Linux >  >> Linux

Jaký je rozdíl mezi použitím `sh` a `source`?

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


Linux
  1. Rozdíl mezi [[ $a ==Z* ]] a [ $a ==Z* ]?

  2. Jaký je rozdíl mezi Redhat a centOS?

  3. Jaký je rozdíl mezi strtok_r a strtok_s v C?

  1. Jaký je rozdíl mezi InnoDB a MyISAM?

  2. Jaký je rozdíl mezi ls a l?

  3. Jaký je rozdíl mezi `su -` a `su --login`?

  1. Jaký je rozdíl mezi insmod a modprobe

  2. Jaký je rozdíl mezi fsck a e2fsck?

  3. Jaký je rozdíl mezi adduser a useradd?