Qual é a diferença entre executar um script Bash e fazer o sourcing dele?

228

Qual é a diferença entre executar um script Bash como A e obter um script Bash como B?

A
> ./myscript

B
> source myscript
    
por Scottie T 11.12.2009 / 16:24

7 respostas

290

Resposta curta: o sourcing executará os comandos no processo atual do shell. executar executará os comandos em um novo processo de shell. ainda confuso? então por favor continue lendo a resposta longa.

Terminologia:

Para esclarecer algumas confusões comuns sobre a sintaxe a ser executada e a sintaxe para a origem:

./myscript

Execute myscript , desde que o arquivo seja executável e localizado no diretório atual. A barra de pontos à esquerda ( ./ ) indica o diretório atual. Isso é necessário porque o diretório atual geralmente não está em $PATH .

myscript

Execute myscript se o arquivo for executável e localizado em algum diretório em $PATH .

source myscript

Origem myscript . o arquivo não precisa ser executável, mas deve ser um script de shell válido. O arquivo pode estar no diretório atual ou em um diretório em $PATH .

. myscript

Origem myscript . Essa sintaxe é definida pelo POSIX . Bash definiu source como um apelido para o comando dot.

Demonstração:

Considere myscript.sh com o seguinte conteúdo:

#!/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

Antes de executarmos o script primeiro, verificamos o ambiente atual:

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

A variável FOO não está definida e estamos no diretório inicial.

Agora, executamos o arquivo:

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

Verifique o ambiente novamente:

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

A variável FOO não está definida e o diretório de trabalho não foi alterado.

A saída do script mostra claramente que a variável foi definida e o diretório foi alterado. A verificação depois mostra que a variável não está definida e o diretório não foi alterado. O que aconteceu? As alterações foram feitas em um shell novo . O shell atual gerou um shell new para executar o script. O script está sendo executado no novo shell e todas as alterações no ambiente entram em vigor no novo shell. Depois que o script é feito, o novo shell é destruído. Todas as alterações no ambiente no novo shell são destruídas com o novo shell. Apenas o texto de saída é impresso no shell atual.

Agora nós fornecemos o arquivo:

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

Verifique o ambiente novamente:

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

A variável FOO é definida e o diretório de trabalho foi alterado.

O fornecimento do script não cria um novo shell. Todos os comandos são executados no shell atual e as alterações no ambiente entram em vigor no shell atual.

Note que neste exemplo simples a saída da execução é a mesma que a do script. Isso nem sempre é necessariamente o caso.

Outra demonstração:

Considere o seguinte script pid.sh :

#!/bin/sh
echo $$

(a variável especial $$ se expande para o PID do processo atual do shell em execução)

Primeiro, imprima o PID do shell atual:

$ echo $$
25009

fonte do script:

$ source pid.sh
25009

Execute o script, observe o PID:

$ ./pid.sh
25011

Fonte novamente:

$ source pid.sh
25009

Execute novamente:

$ ./pid.sh
25013

Você pode ver que a origem do script é executada no mesmo processo, enquanto a execução do script cria um novo processo toda vez. Esse novo processo é o shell novo que foi criado para a execução do script. O fornecimento do script não cria um novo shell e, portanto, o PID permanece o mesmo.

Resumo

Tanto o fornecimento quanto a execução do script executarão os comandos no script linha por linha, como se você tivesse digitado esses comandos manualmente linha por linha.

As diferenças são:

  • Quando você executa o script que está abrindo um novo shell, digite os comandos no novo shell, copie a saída de volta ao seu shell atual e feche o novo Concha. Quaisquer alterações no ambiente entrarão em vigor somente no novo shell e serão perdidas quando o novo shell for fechado.
  • Quando você fonte o script você está digitando os comandos em seu atual shell. Quaisquer alterações no ambiente entrarão em vigor e permanecerão no seu shell atual.

Use a origem se você quiser que o script altere o ambiente no seu shell atualmente em execução. use executar de outra forma.

Veja também:

por 16.08.2010 / 23:58
21

A execução de um script o executa em um processo filho separado, ou seja, uma instância separada do shell é chamada para processar o script. Isso significa que quaisquer variáveis de ambiente, etc., definidas no script não podem ser atualizadas no shell pai (atual).

O fornecimento de um script significa que ele é analisado e executado pelo próprio shell atual. É como se você digitasse o conteúdo do script. Por esse motivo, o script que está sendo originado não precisa ser executável. Mas tem que ser executável se você estiver executando, é claro.

Se você tiver argumentos posicionais no shell atual, eles permanecerão inalterados.

Então, se eu tiver um arquivo a.sh contendo:

echo a $*

e eu faço:

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

Eu recebo algo como:

a Fri Dec 11 07:34:17 PST 2009

Considerando que:

$ set 'date'
$ ./a.sh

me dá:

a

Espero que ajude.

    
por 11.12.2009 / 16:35
7
O

sourcing é essencialmente o mesmo que digitar cada linha do script no prompt de comando, uma de cada vez ...

A execução inicia um novo processo e, em seguida, executa cada linha do script, modificando apenas o ambiente atual com o que ele retorna.

    
por 11.12.2009 / 16:27
4

Como você obtém todas as variáveis extras definidas no script.
Então, se você tiver configurações ou definições de funções, você deve procurar e não executar. As execuções são independentes do ambiente dos pais.

    
por 11.12.2009 / 16:25
4

Além de acima, executar o script como ./myscript requer permissão de execução para o arquivo myscript, enquanto o sourcing não requer nenhuma permissão de execução. É por isso que chmod +x myscript não é necessário antes de source myscript

    
por 23.02.2012 / 08:27
3

Se bem me lembro, a execução do script executa o executável na linha #! com o arquivo de script como um argumento (geralmente iniciando um novo shell e efetivamente obtendo o script no novo shell, como em #!/bin/sh );
enquanto, o sourcing do script executa cada linha em seu ambiente shell atual, o que é útil para transformar seu shell atual (por exemplo, fornecendo uma maneira de definir funções do shell e exportar variáveis de ambiente).

    
por 11.12.2009 / 16:27
2

O comando source executa o script fornecido (a permissão executável é não obrigatória ) no ambiente shell atual , enquanto ./ executa o script executável fornecido em um shell novo .

Além disso, verifique esta resposta, por exemplo: link

    
por 27.03.2015 / 15:04