Qual é a diferença entre sourcing ('.' Ou 'source') e executar um arquivo no bash?

76

Qual é a diferença entre executar um script como este:

./test.sh

e executando um script como este:

. test.sh?

Tentei um script simples de duas linhas para verificar se havia alguma diferença:

#!/bin/bash
ls

Mas ambos . test.she ./test.shretornou a mesma informação.

Natan
fonte
Desculpas se for uma duplicata - após uma investigação mais aprofundada, encontrei algumas páginas com informações relevantes pesquisando 'bash dot' em vez de 'bash'.
Natan
3
Assim como test.shnão é o mesmo que ./test.sh(o primeiro invoca uma PATHpesquisa), assim são . test.she . ./test.shdiferente da mesma forma (o antigo invoca uma PATHpesquisa). Muitos shells parecem incluir implicitamente .no final de PATHuma .pesquisa de caminho, mas esse comportamento não é padrão. Assim, é mais preciso para comparar test.shvs . test.she ./test.shvs . ./test.sh.
Jw013

Respostas:

83

./test.shé executado test.shcomo um programa separado. Pode ser um script bash, se o arquivo test.shcomeçar com #!/bin/bash. Mas poderia ser algo completamente diferente.

. ./test.shexecuta o código do arquivo test.shdentro da instância em execução do bash. Funciona como se o arquivo de conteúdo test.shtivesse sido incluído textualmente em vez da . ./test.shlinha. (Quase: existem alguns detalhes que diferem, como o valor de $BASH_LINENOe o comportamento do returncomponente interno.)

source ./test.shé idêntico ao . ./test.shbash (em outros shells, sourcepode ser um pouco diferente ou não existir completamente; .pois a inclusão está no padrão POSIX).

A diferença mais visível entre executar um script separado ./test.she incluir um script com o .builtin é que, se o test.shscript definir algumas variáveis ​​de ambiente, com um processo separado, apenas o ambiente do processo filho será definido, enquanto que com a inclusão do script, o ambiente do processo único shell está definido. Se você adicionar uma linha foo=barno test.she echo $foono final do script de chamada, você vai ver a diferença:

$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo

$ . ./test.sh
$ echo $foo
bar
Gilles
fonte
17
A adição echo $$ao script também mostrará a diferença bastante clara. A $$variável mantém o PID do shell atual.
1
Outro cenário de uso é usar a . ./test.shchamada de outro script de shell para usar funções descritas em test.sh. Quero dizer, não são apenas as variáveis ​​que você pode definir, você também pode criar novas funções dessa maneira que são chamadas pelo bash ou algum outro script. . /usr/libexec/company/tools; custom_command "variable"
Rqomey 31/07/12
9

A execução de um script da primeira maneira o executa como um processo filho. A terceirização (por outro lado), por outro lado, executa o script como se você inserisse todos os seus comandos no shell atual - se o script definir uma variável, ele permanecerá definido, se o script sair, sua sessão será encerrada. Veja help .para documentação.

choroba
fonte
3

Outra coisa que observo é que, se você tiver um alias como este:

# add into .bashrc_aliases
alias ls='ls -lht'

Com isso, ./test.shvocê obterá uma lssaída normal (e um PID diferente do shell atual):

auraham@pandora:~/iso$ ./test.sh 
dsl-4.4.10.iso  test.sh
3136 # PID

Com . test.shou . ./test.shvocê obterá uma saída mais detalhada (e o mesmo PID que o shell atual):

auraham@pandora:~/iso$ echo $$
2767 # shell PID

auraham@pandora:~/iso$ . test.sh 
total 50M
drwxrwxr-x  2 auraham auraham 4.0K Jul 30 15:41 .
-rwxrwxr-x  1 auraham auraham   32 Jul 30 15:41 test.sh
drwxr-xr-x 50 auraham auraham 4.0K Jul 30 15:30 ..
-rw-rw-r--  1 auraham auraham  50M Jul 28 17:24 dsl-4.4.10.iso
2767 # PID
auraham
fonte
Você pode incluir isso em .bashrc if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi Em seguida, insira seus aliases .bash_aliases.
auraham
Claro, mas você ainda não precisa usar a aliaspalavra - chave? (Talvez seja apenas um erro em você borne - na linha 3?)
Emanuel Berg
totalmente correto, meu erro. Obrigado @EmanuelBerg
auraham
-1

O principal uso para mim para source(ou .) são as funções do bash .

Eu tenho scripts com muitas funções e executo todos eles com o meu .bashrc. As funções "se tornam" comandos, que eu uso com frequência.

Willian Paixao
fonte
Tentei todos os três métodos em .bashrc - source, a posição absoluta do script e o nome do comando (colocando o script em uma pasta PATH) - e todos os três métodos funcionaram.
Emanuel Berg