GNU/Linux >> Linux Esercitazione >  >> Linux

Qual è la differenza tra l'uso di `sh` e `source`?

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


Linux
  1. La differenza tra [[ $a ==Z* ]] e [ $a ==Z* ]?

  2. Qual è la differenza tra Git Switch e Checkout?

  3. Qual è la differenza tra strtok_r e strtok_s in C?

  4. Qual è la differenza tra adduser e useradd?

  5. Qual è la differenza tra `su -` e `su --login`?

Qual è la differenza tra InnoDB e MyISAM?

Qual è la differenza tra Linux e Unix?

Qual è la differenza tra Login e Non-Login Shell

Qual è la differenza tra il comando apt e apt-get?

Che cos'è un hypervisor? Qual è la differenza tra il tipo 1 e 2?

Qual è la differenza tra curl e Wget?