Resposta curta
Em sua pergunta, o segundo comando não usa nem o .
shell embutido nem o source
interno. Em vez disso, você está realmente executando o script em um shell separado, invocando-o pelo nome (como qualquer outro arquivo executável). Isso fornece um conjunto separado de variáveis de ambiente (embora, se você exportar uma variável de ambiente em seu shell pai, ele seja incluído). Se você alterar o /
para um espaço, ele será executado com o .
integrado, o que equivale a source
.
Explicação estendida
Esta é a sintaxe do shell source
embutido, que executa o conteúdo de um script no shell atual (e, portanto, com as variáveis de ambiente do shell atual):
source testenv.sh
Esta é a sintaxe do .
embutido, que faz a mesma coisa que source
:
. testenv.sh
No entanto, essa sintaxe executa o script como um arquivo executável, iniciando um novo shell para executá-lo:
./testenv.sh
Isso não está usando o .
incorporado. Em vez disso, .
faz parte do caminho para o arquivo que você está executando. De um modo geral, você pode executar qualquer arquivo executável em um shell chamando-o com um nome que contenha pelo menos um caractere /
. Para executar um arquivo no diretório atual, precedendo-o por ./
é, portanto, a maneira mais fácil. A menos que o diretório atual esteja no seu PATH
, você não poderá executar o script com o comando testenv.sh
. Isso evita que as pessoas executem acidentalmente arquivos no diretório atual quando pretendem executar um comando do sistema ou algum outro arquivo existente em algum diretório listado na variável de ambiente PATH
.
Como a execução de um arquivo por nome (em vez de usar source
ou .
) o executa em um novo shell, ele terá seu próprio conjunto de variáveis de ambiente. As variáveis de ambiente herdam das variáveis de ambiente do processo de chamada (que, neste caso, é seu shell interativo). No entanto, para que uma variável de ambiente seja passada para o novo shell, um dos seguintes itens deve ser o caso:
-
A variável de ambiente foi exportada. Use o shell
export
embutido para isso. No seu exemplo, você pode usarexport MY_VAR=12345
para definir e exportar a variável em uma etapa ou, se já estiver definida, você pode simplesmente usarexport MY_VAR
. -
A variável de ambiente é explicitamente configurada e passada para o comando que você está executando. Isso geralmente faz isso:
MY_VAR=12345 ./testenv.sh
./
Sintaxe para Scripts Requer uma Linha Hashbang para Funcionar (Corretamente)
A propósito, por favor note que, quando você invoca um executável pelo nome como acima (e não com o .
ou source
shell built-ins), o programa shell é usado para executá-lo é não normalmente determinado por qual shell você está usando. Em vez disso:
-
Para arquivos binários, o kernel pode ser configurado para executar arquivos desse tipo específico. Ele examina os dois primeiros bytes do arquivo para um "número mágico" que indica que tipo de executável binário é. É assim que os binários executáveis podem ser executados.
Obviamente, isso é extremamente importante, porque um script não pode ser executado sem um shell ou outro interpretador, que é um binário executável! Além disso, muitos comandos e aplicativos são compilados em binários em vez de scripts.(
#!
é a representação de texto do "número mágico" indicando um executável de texto.) -
Para arquivos que devem ser executados em um shell ou outra linguagem interpretada, a primeira linha se parece com:
#!/bin/sh
/bin/sh
pode ser substituído por qualquer outro shell ou intérprete destinado a executar o programa. Por exemplo, um programa em Python pode começar com a linha:#!/usr/bin/python
Essas linhas são chamadas de hashbang, shebang e vários outros nomes semelhantes. Veja esta entrada do FOLDOC , esta Artigo da Wikipédia e É #! / Bin / sh lido pelo intérprete para mais informações.
-
Se um arquivo de texto for marcado como executável e você executá-lo a partir do seu shell (como
./filename
), mas não começa com#!
, o kernel falha ao executá-lo. No entanto, vendo que isso aconteceu, seu shell irá tentar executá-lo passando seu nome para algum shell. Existem poucos requisitos colocados no que shell que é ( "o shell deve executar um comando equivalente a ter um shell invocado ..." ). Na prática , alguns shells - incluindobash
* - executam outra instância deles mesmos, enquanto outros usam/bin/sh
.É altamente recomendável que você evite isso e use uma hashbang line (ou execute o script passando-o ao interpretador desejado, por exemplo,bash filename
).* manual do GNU Bash , 3.7.2 Comando de pesquisa e execução : "Se esta execução falha porque o arquivo não está no formato executável, e o arquivo não é um diretório, ele é considerado um script de shell e o shell o executa conforme descrito em Shell Scripts . "