Qual è la differenza tra sourcing ('.' O 'source') ed eseguire un file in bash?


76

Qual è la differenza tra l'esecuzione di uno script come questo:

./test.sh

ed eseguendo uno script come questo:

. test.sh?

Ho provato un semplice script a due righe per vedere se riuscivo a trovare se c'era una differenza:

#!/bin/bash
ls

Ma entrambi . test.she hanno ./test.shrestituito le stesse informazioni.


Mi scuso se questo è un duplicato: dopo ulteriori indagini, ho trovato alcune pagine con informazioni pertinenti cercando "punto bash" anziché "bash".
Natan,

3
Così come test.shnon è lo stesso di ./test.sh(il primo invoca una PATHricerca), così sono . test.she sono . ./test.shdiversi allo stesso modo (il primo invoca una PATHricerca). Molte shell sembrano includere implicitamente .alla fine di PATHquando si esegue una .ricerca di percorso, ma questo comportamento non è standard. Così, è più corretto confrontare test.shvs . test.she ./test.shcontro . ./test.sh.
jw013,

Risposte:


83

./test.shfunziona test.shcome un programma separato. Può capitare di essere uno script bash, se il file test.shinizia con #!/bin/bash. Ma potrebbe essere qualcos'altro del tutto.

. ./test.shesegue il codice del file test.shall'interno dell'istanza corrente di bash. Funziona come se il file di contenuto test.shfosse stato incluso testualmente invece della . ./test.shriga. (Quasi: ci sono alcuni dettagli che differiscono, come il valore $BASH_LINENOe il comportamento dell'integrato return.)

source ./test.shè identico a . ./test.shin bash (in altre shell, sourcepuò essere leggermente diverso o non esistere del tutto; .poiché l'inclusione è nello standard POSIX).

La differenza più comunemente visibile tra l'esecuzione di uno script separato ./test.she l'inclusione di uno script con .incorporato è che se lo test.shscript imposta alcune variabili di ambiente, con un processo separato, viene impostato solo l'ambiente del processo figlio, mentre con l'inclusione dello script, l'ambiente del solo processo di shell impostato. Se si aggiunge una linea foo=bardi test.she echo $fooalla fine dello script di chiamata, si vedrà la differenza:

$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo

$ . ./test.sh
$ echo $foo
bar

17
Anche l'aggiunta echo $$allo script mostrerà la differenza abbastanza chiara. La $$variabile contiene il PID della shell corrente.

1
Un altro scenario di utilizzo è l'utilizzo della . ./test.shchiamata dall'interno di un altro script shell per utilizzare le funzioni descritte in test.sh. Voglio dire, non sono solo le variabili che puoi impostare, puoi anche creare nuove funzioni in questo modo che possono essere richiamate da bash o da qualche altro script. . /usr/libexec/company/tools; custom_command "variable"
Rqomey,

9

L'esecuzione di uno script nel primo modo lo esegue come un processo figlio. Il sourcing (il secondo modo), invece, esegue lo script come se tutti i suoi comandi fossero stati immessi nella shell corrente - se lo script imposta una variabile, rimarrà impostato, se lo script esce, la sessione verrà chiusa. Vedi help .per la documentazione.


3

Un'altra cosa che noto è che se hai un alias come questo:

# add into .bashrc_aliases
alias ls='ls -lht'

Con ./test.shotterrai un lsoutput normale (e un PID diverso rispetto alla shell corrente):

auraham@pandora:~/iso$ ./test.sh 
dsl-4.4.10.iso  test.sh
3136 # PID

Con . test.sho . ./test.shotterrai un output più dettagliato (e lo stesso PID della shell corrente):

auraham@pandora:~/iso$ echo $$
2767 # shell PID

auraham@pandora:~/iso$ . test.sh 
total 50M
drwxrwxr-x  2 auraham auraham 4.0K Jul 30 15:41 .
-rwxrwxr-x  1 auraham auraham   32 Jul 30 15:41 test.sh
drwxr-xr-x 50 auraham auraham 4.0K Jul 30 15:30 ..
-rw-rw-r--  1 auraham auraham  50M Jul 28 17:24 dsl-4.4.10.iso
2767 # PID

Puoi includerlo in .bashrc if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi Quindi, inserisci i tuoi alias .bash_aliases.
Auraham

Certo, ma non devi ancora usare la aliasparola chiave? (Forse è solo un errore nel tuo post - sulla linea 3?)
Emanuel Berg,

totalmente corretto, errore mio. Grazie @EmanuelBerg
auraham,

-1

L'utilizzo principale per me source(o .) sono le funzioni bash .

Ho degli script con molte funzioni e li eseguo tutti con il mio .bashrc. Le funzioni "diventano" comandi, che uso spesso.


Ho provato tutti e tre i metodi in .bashrc - sorgente, la posizione assoluta dello script e il nome del comando (posizionando lo script in una cartella PATH) - e tutti e tre i metodi hanno funzionato.
Emanuel Berg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.