Respostas:
A fonte de um script executará os comandos no processo atual do shell.
A execução de um script executará os comandos em um novo processo de shell.
Use source se desejar que o script altere o ambiente no shell em execução no momento. use execute caso contrário.
Se você ainda está confuso, continue lendo.
Para esclarecer alguma confusão comum sobre a sintaxe a ser executada e a sintaxe na origem:
./myscript
Isso será executado, myscript
desde que o arquivo seja executável e localizado no diretório atual. O ponto inicial e a barra ( ./
) denotam o diretório atual. Isso é necessário porque o diretório atual não é geralmente (e geralmente não deve ser) em $PATH
.
myscript
Isso será executado myscript
se o arquivo for executável e estiver localizado em algum diretório em $PATH
.
source myscript
Isso será 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 em $PATH
.
. myscript
Isso também será fonte myscript
. Essa "ortografia" é a oficial, conforme definido pelo POSIX . Bash definido source
como um alias para o ponto.
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 executar 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 configurada 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 novo shell. O shell atual 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. Após a conclusão do script, o novo shell é destruído. Todas as alterações no ambiente no novo shell são destruídas com o novo shell. Somente 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 está definida e o diretório de trabalho foi alterado.
A terceirização 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.
Observe que, neste exemplo simples, a saída da execução é igual à obtenção do script. Este não é necessariamente sempre o caso.
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
Origem 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 fonte 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 terceirização do script não cria um novo shell e, portanto, o PID permanece o mesmo.
O fornecimento e a execução do script executarão os comandos no script linha por linha, como se você digitasse esses comandos manualmente, linha por linha.
As diferenças são:
Use source se desejar que o script altere o ambiente no shell em execução no momento. use execute caso contrário.
Veja também:
source myscript.sh
e . myscript.sh
?
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 qualquer variável de ambiente etc. definida no script não pode ser atualizada no shell pai (atual).
Fornecer 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 deve ser executável se você estiver 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.
o fornecimento é 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 pelo que ele retorna.
Além disso, a execução do script conforme ./myscript
requer permissão de execução para o arquivo myscript, enquanto a fonte não requer permissão de execução. É por isso que chmod +x myscript
não é necessário antessource myscript
bash myscript
.
No fornecimento, você obtém todas as variáveis extras definidas no script.
Portanto, se você tiver configurações ou definições de funções, deverá originar e não executar. As execuções são independentes do ambiente dos pais.
Se bem me lembro, a execução do script executa o executável na #!
linha com o arquivo de script como argumento (normalmente iniciando um novo shell e efetivamente fornecendo o script para o novo shell, como em #!/bin/sh
);
enquanto que o fornecimento do script executa cada linha no seu ambiente atual de shell, o que é útil para alterar seu shell atual (por exemplo, fornecendo uma maneira de definir funções de shell e exportar variáveis de ambiente).
source
O comando executa o script fornecido (a permissão executável não é obrigatória ) no ambiente atual do shell, enquanto ./
executa o script executável fornecido em um novo shell.
Além disso, verifique esta resposta, por exemplo: https://superuser.com/a/894748/432100