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


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

A
> ./myscript

B
> source myscript

213


origem




Respostas:


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 alguma confusão comum sobre a sintaxe a ser executada e a sintaxe para a fonte:

./myscript

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

myscript

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

source myscript

Fonte  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 $PATH.

. myscript

Fonte  myscript. Esta sintaxe é definido por POSIX. Bash definido source como um alias para o comando dot.

Demonstração:

Considerar 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á definido e estamos no diretório inicial.

Agora nós executar 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á definido 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 mudanças foram feitas em um Novo Concha. o atual shell gerou um Novo shell 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 fonte 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 são efetivadas 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 seguir o script pid.sh:

#!/bin/sh
echo $$

(a variável especial $$ 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 Novo shell que foi criado para a execução do script. A obtenção 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ê executar o roteiro que você está abrindo Novo shell, digite os comandos no novo shell, copie a saída de volta para o shell atual e feche o novo shell. 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 que você está digitando os comandos em seu atual Concha. Quaisquer alterações no ambiente entrarão em vigor e permanecerão no seu shell atual.

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


Veja também:


277



Um uso de terceirização é criar uma forma rudimentar de arquivo de configuração para seus scripts. Você começa definindo diversas variáveis ​​para valores padrão e, em seguida, fonte em algo como myscript.conf - e esse script de origem pode ter instruções de atribuição que substituem os valores desejados. Como o script de origem não começa com # / bin / bash, ele não é incentivado a executá-lo diretamente. - LawrenceC
Portanto, source é como executá-lo em um escopo global, e a execução cria um novo escopo local. Isso pode ser estendido para uma função em um script? executar uma função (normalmente) ou "fonte" isso? - aliteralmind
Chamar uma função de shell normalmente se comporta muito como o sourcing. chamar uma função de shell dentro de um subshell se comporta de maneira semelhante à execução. - lesmana
Existe uma diferença entre usar source myscript.sh e . myscript.sh? - Holloway
praticamente nenhuma diferença se usando bash. source é um alias para pontuar no bash. - lesmana


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 pode ser atualizado no shell pai (atual).

A obtenção 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ê está executando, é claro.

Se você tiver argumentos posicionais no shell atual, eles não serão alterados.

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

Enquanto que:

$ set `date`
$ ./a.sh

me dá:

a

Espero que ajude.


21



Embora esta resposta seja correta em todos os sentidos, acho muito difícil de entender, porque é demonstrado usando um outro conceito (configuração de parâmetros posicionais), que é, na minha opinião, ainda mais confuso do que a diferença de terceirização e execução em si. - lesmana


O sourcing é essencialmente o mesmo que digitar cada linha do script no prompt de comando, um 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.


5





Sourcing 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.


4





Além de acima, executando 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 source myscript


4



É verdade, mas se isso é um problema, você sempre pode executar bash myscript. - Daniel Beck♦


Se bem me lembro, a execução do script executa o executável no #! linha com o arquivo de script como um argumento (geralmente iniciando um novo shell e efetivamente sourcing o script para o novo shell, como com #!/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).


3





source comando executa o script fornecido (permissão executável é não obrigatório) no atual ambiente shell, enquanto ./ executa o fornecido executável roteiro em um Novo Concha.

Além disso, verifique esta resposta, por exemplo: https://superuser.com/a/894748/432100


2