Qual é a diferença entre a execução de um guião Bash versus a sua aquisição?
Qual é a diferença entre executar um guião Bash como A e obter um guião Bash como B?
A
> ./myscript
B
> source myscript
Sourcing um script irá executar os comandos no processo current shell.
Executar um script executará os comandos num processo novo shell.
Use a fonte se quiser que o script altere o ambiente na sua shell actualmente em execução. use execute de outra forma.
Se ainda estiver confuso, por favor continue a ler.
Para esclarecer alguma confusão comum sobre a sintaxe a executar e a sintaxe à fonte:
./myscript
Isto irá executar myscript
desde que o ficheiro seja executável e localizado no directório actual. O ponto e barra (./
) denota o directório actual. Isto é necessário porque o directório actual normalmente não está (e normalmente não deveria estar) em $PATH
.
myscript
Isto irá executar myscript
se o ficheiro for executável e estiver localizado em algum directório em $PATH
.
source myscript
Isto irá fonte myscript
. O ficheiro não precisa de ser executável, mas deve ser um script de shell válido. O ficheiro pode estar no directório actual ou num directório em $PATH
.
. myscript
Isto também source* myscript
. Esta “ortografia” é a oficial tal como definida por POSIX . Bash definido source
como um alias para o ponto.
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 guião, verificamos primeiro o ambiente actual:
$ env | grep FOO
$ echo $PWD
/home/lesmana
A variável FOO
não está definida e nós estamos no directório home.
Agora executamos o ficheiro:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Verifique novamente o ambiente:
$ env | grep FOO
$ echo $PWD
/home/lesmana
A variável FOO
não está definida e o directório de trabalho não mudou.
A saída do script mostra claramente que a variável foi definida e que o directório foi alterado. A verificação posterior mostra que a variável não está definida e o directório não foi alterado. O que aconteceu? As alterações foram feitas numa nova shell. A current shell gerou uma new shell para executar o script. O script está a correr na nova shell e todas as alterações ao ambiente têm efeito na nova shell. Após a script ter sido feita, a nova shell é destruída. Todas as alterações ao ambiente na nova concha são destruídas com a nova concha. Apenas o texto de saída é impresso na shell actual.
Agora nós código* do ficheiro:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Verifique novamente o ambiente:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
A variável FOO está definida e o directório de trabalho foi alterado.
O script não cria uma nova shell. Todos os comandos são executados na shell actual e as alterações ao ambiente têm efeito na shell actual.
Note que neste exemplo simples o resultado da execução é o mesmo que o sourcing do script. Este nem sempre é necessariamente o caso.
Considere o seguinte script pid.sh
:
#!/bin/sh
echo $$
(a variável especial $$
expande-se para o PID do actual processo shell em execução)
Primeira impressão do PID da shell actual:
$ echo $$
25009
Fonte do script:
$ source pid.sh
25009
Executar o script, anote o PID:
$ ./pid.sh
25011
Fonte novamente:
$ source pid.sh
25009
Executar novamente:
$ ./pid.sh
25013
Pode ver que o sourcing do script corre no mesmo processo enquanto executa o script cria sempre um novo processo. Esse novo processo é a nova shell que foi criada para a execução do guião. O sourcing do script não cria uma nova shell e assim o PID permanece o mesmo.
Tanto o sourcing como a execução do script executarão os comandos no script linha a linha, como se tivesse digitado esses comandos linha a linha.
As diferenças são:
Use a fonte se quiser que o script altere o ambiente na sua shell actualmente em execução. use execute de outra forma.
Veja também:
A execução de um guião executa-o num processo infantil separado, ou seja, é invocada uma instância separada de concha para processar o guião. Isto significa que qualquer variável de ambiente, etc., definida no script não pode ser actualizada na shell pai (actual).
A obtenção de um script significa que este é analisado e executado pela própria shell (actual). É como se tivesse digitado o conteúdo do script. Por esta razão, o script de origem não precisa de ser executável. Mas tem de ser executável se o estiver a executar, claro.
Se tiver argumentos posicionais na shell actual, eles mantêm-se inalterados.
Assim, se eu tiver um ficheiro a.sh
contendo:
echo a $*
e eu tenho:
$ set `date`
$ source ./a.sh
recebo algo como:
:
a Fri Dec 11 07:34:17 PST 2009
Considerando
$ set `date`
$ ./a.sh
dá-me:
a
Esperança que ajuda.
sourcing é essencialmente o mesmo que digitar cada linha do guião no prompt de comando, um de cada vez…
Execução inicia um novo processo e depois executa cada linha do guião, modificando apenas o ambiente actual pelo que este retorna.
A aquisição obtém todas as variáveis extra definidas no guião.
Assim, se tiver configurações ou definições de funções, deve fazer a fonte e não executar. As execuções são independentes do ambiente dos pais.
source
executa o script fornecido (a permissão executável é não é obrigatória* ) no current* ambiente shell, enquanto ./
executa o script fornecido executable* numa novo shell.
Também, verifique esta resposta por exemplo: https://superuser.com/a/894748/432100