La differenza principale è che vengono eseguiti in un processo diverso.
Quindi se source
un file foo
che fa un cd
, la shell di sourcing (ad es. la tua shell interattiva nel terminale) è interessata (e la sua directory corrente cambierà)
Se esegui sh foo
il cd
non influisce sulla shell di sourcing, solo sul sh
appena creato processo che esegue foo
Leggi la Guida avanzata agli script Bash.
Come altri hanno già detto, quando esegui sh test.sh
, qualsiasi modifica che test.sh
make al tuo ambiente shell non persisterà dopo che il processo è terminato.
Tuttavia, tieni anche presente che qualsiasi elemento del tuo ambiente che non viene esportato (ad es. variabili, alias e funzioni di shell) non sarà disponibile per il codice in test.sh
quando viene eseguito come sottoprocesso (cioè con sh test.sh
).
Ad esempio:
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
Esempio 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$
Quando chiami il source
o .
(l'uno è un alias dell'altro. source
cmd not POSIX - una specie di bashism ), carichi ed esegui uno script di shell nella corrente processo shell . Quindi puoi
- leggere le variabili impostate nello script di origine,
- usa le funzioni definite al suo interno.
- e persino eseguire fork e/o sottoprocessi se lo script lo fa.
Quando chiami il sh
, avvii un fork (processo secondario o figlio ) che esegue una nuova sessione di /bin/sh
(che spesso è un collegamento simbolico a bash
). In questo caso, le variabili d'ambiente impostate dal sub-script verrebbero eliminate quando il sub-script termina.
Attenzione :sh
potrebbe essere un collegamento simbolico a un altro guscio.
Campione pratico
Ad esempio, se desideri modificare la directory di lavoro corrente in un modo specifico, non potresti farlo
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
Questo non farà ciò che ti aspetti:
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
perché la directory di lavoro corrente fa parte dell'ambiente e myCd2Doc.sh
verrebbe eseguito in una subshell .
Ma:
$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
Dai un'occhiata a mycd
funzione!! (Con completamento bash basato su Associative Array ).
Livello di esecuzione $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.
Ricorsione (quando uno script viene eseguito da se stesso)
$ 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.
Un po' più in là
$ 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
( PID corrente ($$
==ID processo ) sono lo stesso identificatore di SID (ID sessione ). Non è sempre vero.)
$ ./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
Punto .
è un alias di source
. Quindi l'unica differenza tra due comandi è slash
sostituito da space
.
E un finale prova:
$ 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.
... Potresti notare un diverso comportamento tra le due sintassi.;-)