Qual é a diferença entre executar "bash script.sh" e "./script.sh"?

42

Se script.sh é apenas algo típico como

#!/bin/bash
echo "Hello World!"

Existe uma maneira preferida de executar o script? Eu acho que você primeiro tem que chmod para que se torne executável?

user72136
fonte

Respostas:

56

Para o seu script específico, qualquer uma das maneiras funcionará, exceto que ./script.shrequer execução e bits legíveis, enquanto bash script.shrequer apenas bits legíveis.


O motivo da diferença dos requisitos de permissão está na maneira como o programa que interpreta o seu script é carregado:

  • ./script.sh faz seu shell executar o arquivo como se fosse um executável regular.

O shell se bifurca e usa uma chamada do sistema (por exemplo execve) para fazer o sistema operacional executar o arquivo no processo bifurcado. O sistema operacional verificará as permissões do arquivo (portanto, o bit de execução precisa ser definido) e encaminhará a solicitação ao carregador do programa , que analisa o arquivo e determina como executá-lo. No Linux, os executáveis ​​compilados começam com um número mágico ELF , enquanto os scripts começam com um #!( hashbang ). Um cabeçalho hashbang significa que o arquivo é um script e precisa ser interpretado pelo programa especificado após o hashbang. Isso permite que um script em si diga ao sistema como interpretá-lo.

Com o seu script, o carregador de programas será executado /bin/bashe transmitido ./script.sh como o argumento da linha de comandos.

  • bash script.shfaz seu shell rodar bashe passar script.shcomo o argumento da linha de comando

Portanto, o sistema operacional será carregado bash(nem mesmo olhando script.sh, porque é apenas um argumento da linha de comando). O bashprocesso criado interpretará o script.shporque é passado como o argumento da linha de comando. Como script.shé lido apenas bashcomo um arquivo regular, o bit de execução não é necessário.


Eu recomendo o uso ./script.sh, porque você pode não saber qual intérprete o script está exigindo. Então deixe o carregador do programa determinar isso para você.

SkyDan
fonte
3
Se o bit executável não está definida, você também pode executar o script fazendo "./script.sh."
Dog Eat World Cat
1
@ Dog Você está correto. O ponto é um atalho para o comando interno 'source', que executa o script no processo atual do bash. Portanto, apenas o bit legível é necessário.
SkyDan
5
@Dogeatcatworld enquanto isso é verdade, correr . ./script.shnão é a mesma coisa que bash script.sh(ou ./script.shConsidere o script. #!/usr/bin/python -V<Newline> print test.
Casey
12
Cuidado que o fornecimento de um script pode resultar na contaminação da sessão interativa. Por exemplo, se um script alterar a variável de ambiente PATH, essa alteração afetará os comandos executados após a origem. Essa abordagem deve ser realmente reservada para situações nas quais você depende dos efeitos colaterais (scripts de configuração do ambiente e similares). Para outras situações em que você não pode alterar as permissões, executar o comando na linha shebang, seguido pelo nome do script, é a abordagem mais segura.
ctt
6
Observe que, se você cria um script no diretório atual, não precisa usar ./ ; apenas diga . script.sh. Mas concordo com as pessoas que desencorajam o uso do .comando em scripts que não deveriam ser invocados dessa maneira. Estou surpreso que ninguém tenha mencionado que, se o script contiver exitcomandos e você o originar, ele poderá desconectá-lo. Um problema menos grave seria se o script fizesse a cd, pois isso também afetaria o shell pai (interativo).
Scott
18

bash script.shchama o script diretamente usando o bash.
./script.shestá usando o shebang #!/bin/bashpara determinar como executar.

Se você realmente quer saber, qual binário é executado, se você fizer um, bash script.shpoderá descobrir which bash.

Portanto, no seu exemplo, não faz diferença. Sim, você deve chmod +x script.shpoder executá-lo diretamente via ./script.sh.

xx4h
fonte
2
Bem, não faz diferença supor que /bin/bashseja o primeiro bashno seu $PATH.
CJM
Você está certo. E a coisa toda #!/bin/bashsó funciona se houver uma/bin/bash
xx4h
O Bash (versão 4.2.37) no meu sistema executa scripts mesmo sem o bit de execução definido. Por que você diz que o bit de execução é necessário?
11119 SkyDan
Sim, o bit de execução é necessário apenas invocando via ./script.sh.
Xx4h
4

Crie um arquivo Delete_Self.sh assim:

 #!/bin/rm

 echo I am still here!

Execute este script como sh Delete_Self.shvocê verá "Eu ainda estou aqui!" ecoou de volta.

Torne-o executável e execute-o como ./Delete_Self.shvocê verá que nada é repetido, enquanto o arquivo em Delete_Self.shsi desapareceu.

Então a diferença é que:

  • bash script.shirá ignorar o #! linha, porque o bash é especificado como o programa para executar o script.sh.
  • ./script.shvai ler o #! linha para determinar o programa a ser executado script.sh.
David
fonte
+1 para o bom exemplo
ThisaruG
1

Além das outras respostas, é útil saber a diferença entre executar um script via ./script.sh(i) e fonte ./script.sh(ii) - A versão (i) cria um novo shell para executar o comando, enquanto (ii) o executa no shell atual - que pode ser obrigatório se o executável alterar variáveis ​​de ambiente que precisam ser preservadas após a saída do executável. Por exemplo, para ativar um ambiente python conda, o seguinte deve ser usado:

source activate my_env

NB Outra alternativa a sourceque você pode encontrar é o .embutido, ou seja,

. activate my_env
einonm
fonte