2009-12-11 15:24:17 +0000 2009-12-11 15:24:17 +0000
302
302

Qual è la differenza tra l'esecuzione di uno script Bash e il suo sourcing?

Qual è la differenza tra l'esecuzione di uno script Bash come A e il sourcing di uno script Bash come B?

A
> ./myscript

B
> source myscript

Risposte (6)

369
369
369
2010-08-16 21:58:48 +0000

Sourcing uno script eseguirà i comandi nel processo corrente della shell.

Eseguire uno script eseguirà i comandi in un nuovo processo di shell.

Usa source se vuoi che lo script cambi l'ambiente nella tua shell correntemente in esecuzione, altrimenti usa execute.

Se siete ancora confusi, continuate a leggere.

Terminologia

Per chiarire una certa confusione comune sulla sintassi di execute e la sintassi di source:

./myscript

Questo eseguirà myscript purché il file sia eseguibile e si trovi nella directory corrente. Il punto e la barra iniziale (./) indicano la directory corrente. Questo è necessario perché la directory corrente di solito non è (e di solito non dovrebbe essere) in $PATH.

myscript

Questo eseguirà myscript se il file è eseguibile e si trova in qualche directory in $PATH.

source myscript

Questo sorgerà myscript. Non è necessario che il file sia eseguibile, ma deve essere uno script di shell valido. Il file può essere nella directory corrente o in una directory in $PATH.

. myscript

Anche questo sorgerà myscript. Questo “spelling” è quello ufficiale definito da POSIX . Bash ha definito source come alias del punto.

Dimostrazione

Consideriamo myscript.sh con il seguente contenuto:

#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD

Prima di eseguire lo script controlliamo l'ambiente corrente:

$ env | grep FOO
$ echo $PWD
/home/lesmana

La variabile FOO non è definita e siamo nella home directory.

Ora eseguiamo il file:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Controlla di nuovo l'ambiente:

$ env | grep FOO
$ echo $PWD
/home/lesmana

La variabile FOO non è impostata e la directory di lavoro non è cambiata.

L'output dello script mostra chiaramente che la variabile è stata impostata e la directory è stata cambiata. Il controllo successivo mostra che la variabile non è impostata e la directory non è cambiata. Cosa è successo? Le modifiche sono state fatte in una nuova shell. La shell corrente ha generato una nuova shell per eseguire lo script. Lo script è in esecuzione nella nuova shell e tutti i cambiamenti all'ambiente hanno effetto nella nuova shell. Dopo che lo script è finito, la nuova shell viene distrutta. Tutte le modifiche all'ambiente nella nuova shell vengono distrutte con la nuova shell. Solo il testo in uscita viene stampato nella shell corrente.

Ora noi sorgiamo il file:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Controlla di nuovo l'ambiente:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

La variabile FOO è impostata e la directory di lavoro è cambiata.

La creazione dello script non crea una nuova shell. Tutti i comandi vengono eseguiti nella shell corrente e i cambiamenti all'ambiente hanno effetto nella shell corrente.

Notate che in questo semplice esempio l'output dell'esecuzione è lo stesso del sourcing dello script. Questo non è necessariamente sempre il caso.

Un'altra dimostrazione

Considerate il seguente script pid.sh:

#!/bin/sh
echo $$

(la variabile speciale $$ si espande al PID del processo corrente della shell in esecuzione)

Prima stampa il PID della shell corrente:

$ echo $$
25009

Source lo script:

$ source pid.sh
25009

Esegui lo script, nota il PID:

$ ./pid.sh
25011

Fonte di nuovo:

$ source pid.sh
25009

Esegui di nuovo:

$ ./pid.sh
25013

Puoi vedere che il sourcing dello script gira nello stesso processo mentre l'esecuzione dello script crea un nuovo processo ogni volta. Questo nuovo processo è la nuova shell che è stata creata per l'esecuzione dello script. Il sourcing dello script non crea una nuova shell e quindi il PID rimane lo stesso.

Riepilogo

Sia il sourcing che l'esecuzione dello script eseguiranno i comandi nello script linea per linea, come se li aveste digitati a mano linea per linea.

Le differenze sono:

  • Quando si esegue lo script si apre una nuova shell, si digitano i comandi nella nuova shell, si copia l'output nella shell corrente, poi si chiude la nuova shell. Qualsiasi modifica all'ambiente avrà effetto solo nella nuova shell e sarà persa una volta chiusa la nuova shell.
  • Quando source lo script stai digitando i comandi nella tua corrente shell. Qualsiasi cambiamento all'ambiente avrà effetto e rimarrà nella tua shell corrente.

Usa source se vuoi che lo script cambi l'ambiente nella tua shell corrente, altrimenti usa execute.


Vedi anche:

23
23
23
2009-12-11 15:35:56 +0000

L'esecuzione di uno script lo esegue in un processo figlio separato, cioè viene invocata un'istanza separata di shell per elaborare lo script. Questo significa che qualsiasi variabile d'ambiente ecc. definita nello script non può essere aggiornata nella shell madre (corrente).

Sourcing di uno script significa che viene analizzato ed eseguito dalla shell corrente stessa. È come se si digitasse il contenuto dello script. Per questo motivo, non è necessario che lo script che viene estratto sia eseguibile. Ma deve essere eseguibile se lo state eseguendo, naturalmente.

Se avete argomenti posizionali nella shell corrente, sono invariati.

Quindi se ho un file a.sh contenente:

echo a $*

e faccio:

$ set `date`
$ source ./a.sh

ottengo qualcosa come:

a Fri Dec 11 07:34:17 PST 2009

considerando che:

$ set `date`
$ ./a.sh

mi dà:

a

Spero che questo aiuti.

9
9
9
2009-12-11 15:27:08 +0000

sourcing è essenzialmente lo stesso che digitare ogni linea dello script al prompt dei comandi una alla volta…

L'esecuzione avvia un nuovo processo e poi esegue ogni linea dello script, modificando l'ambiente corrente solo per ciò che restituisce.

6
6
6
2012-02-23 07:27:43 +0000

In aggiunta a quanto sopra, l'esecuzione dello script come ./myscript richiede il permesso di esecuzione per il file myscript mentre il sourcing non richiede alcun permesso di esecuzione. Ecco perché chmod +x myscript non è richiesto prima di source myscript

5
5
5
2009-12-11 15:25:38 +0000

Sourcing si ottengono tutte le variabili extra definite nello script.
Quindi se avete configurazioni o definizioni di funzioni dovreste fare il source e non l'esecuzione. Le esecuzioni sono indipendenti dall'ambiente dei genitori.

2
2
2
2015-03-27 14:04:20 +0000

Il comando source esegue lo script fornito (il permesso eseguibile è non obbligatorio ) nell'ambiente corrente della shell, mentre ./ esegue lo script eseguibile fornito in una nuova shell.

Inoltre, controllate questa risposta per esempio: https://superuser.com/a/894748/432100