Qual é a diferença entre o sourcing ('.' ou 'source') e a execução de um arquivo no bash?

65

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

./test.sh

e executando um script como este:

. test.sh ?

Eu tentei um script simples de duas linhas para ver se conseguia encontrar uma diferença:

#!/bin/bash
ls

Mas os dois . test.sh e ./test.sh retornaram as mesmas informações.

    
por Natan 25.07.2012 / 03:11

4 respostas

73

./test.sh corre test.sh como um programa separado. Pode acontecer de ser um script bash, se o arquivo test.sh começar com #!/bin/bash . Mas poderia ser algo completamente diferente.

. ./test.sh executa o código do arquivo test.sh dentro da instância em execução do bash. Funciona como se o arquivo de conteúdo test.sh tivesse sido incluído textualmente, em vez da linha . ./test.sh . (Quase: há alguns detalhes que diferem, como o valor de $BASH_LINENO e o comportamento do return incorporado.)

source ./test.sh é idêntico a . ./test.sh no bash (em outros shells, source pode ser ligeiramente diferente ou não existir completamente; . para inclusão está no padrão POSIX).

A diferença mais comumente visível entre executar um script separado com ./test.sh e incluir um script com o . incorporado é que, se o script test.sh definir algumas variáveis de ambiente, com um processo separado, apenas o ambiente do processo filho é definido, enquanto que, com a inclusão de script, o ambiente do processo de shell único é definido. Se você adicionar uma linha foo=bar em test.sh e echo $foo no final do script de chamada, verá a diferença:

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

$ . ./test.sh
$ echo $foo
bar
    
por 25.07.2012 / 03:27
9

Executando um script, a primeira maneira é executada como um processo filho. A terceirização (a segunda maneira), por outro lado, executa o script como se você tivesse inserido todos os seus comandos no shell atual - se o script definir uma variável, ela permanecerá definida, se o script sair, sua sessão será encerrada. Veja help . para documentação.

    
por 25.07.2012 / 03:17
3

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

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

Com ./test.sh , você obterá uma saída ls normal (e um PID diferente do shell atual):

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

Com . test.sh ou . ./test.sh , você 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
    
por 30.07.2012 / 22:44
-1

O principal uso para mim de source (ou . ) é funções bash .

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

    
por 25.07.2012 / 04:29

Tags