O mesmo script aberto de três maneiras diferentes produz três resultados diferentes. Por quê? [duplicado]

7

Eu tenho um exemplo de script (o crédito vai para kos ):

#!/bin/bash
cat <(cat /etc/lsb-release)

Salvei esse script como somename.sh no meu diretório pessoal.

Agora, eu tento abrir este arquivo de três maneiras diferentes:

sh somename.sh

bash somename.sh

./somename.sh

Então, eu tenho duas perguntas:

  1. Por que as saídas para os comandos acima são diferentes apesar de estarem executando o mesmo script?

    • sh produz um erro de sintaxe

    • bash produz o resultado desejado

    • ./ apresenta um erro de permissão negada

  2. Por que é necessário conceder a permissão executável do script somente ao executar o script usando ./ e não é necessário nos outros casos?

Obrigado antecipadamente!

EDITAR : A primeira parte pode ser semelhante à duplicada vinculada a uma, mas eu tinha uma segunda pergunta também.

    
por Raphael 26.12.2015 / 12:19

3 respostas

8

Como discutimos no bate-papo:

  1. sh script produz um erro porque chamar o interpretador diretamente (neste caso, sh ) ignora o shebang, e o script é executado em sh ; sh não suporta substituições de processos ( <([...]) ), que são Bash-isms, portanto, o script sai com erro.

    bash script não produz um erro porque, apesar do shebang ser ignorado, o script ainda é executado no Bash, que suporta substituições de processos.

    ./script produz um erro porque script não é executável.

  2. Para executar um script com ./ você deve ter o bit de execução para o seu usuário definido no script, isso é uma restrição do sistema operacional.

    Portanto, a pergunta é: por que o bash script não exige que o bit de execução seja definido para o usuário em script ?

    Isso porque, ao executar bash script , o script é lido pelo Bash, e o Bash tem o bit de execução definido para o usuário.

    Isso significa que o Bash, com permissão para executar código, pode "ignorar" a restrição do sistema operacional nesse script, e todas as necessidades do script devem ser legíveis pelo Bash.

por kos 26.12.2015 / 12:59
5
  • sh é um link simbólico para dash shell e produz um erro de sintaxe porque não há sintaxe <( . . .) in sh . É apenas no bash (e em zsh e ksh , se bem me lembro).

  • bash produz o resultado desejado porque está na sintaxe bash direita, nada de errado

  • ./ dá um erro de Permissão negada porque você basicamente diz "Ei, shell, olha as permissões daquele arquivo e olha para a primeira linha (aquela com #!/bin/bash ) no meu diretório atual e descobrir como executar esse script para mim ". (nota lateral: se você tivesse o script em um local incluído na variável $PATH , você executaria apenas myScriptName.sh e pronto, mas a ideia seria a mesma, precisamos verificar as permissões de execução e qual interpretador usar)

Antes de você estar executando bash e dash e solicitando a leitura de comandos do arquivo. bash e dash são executáveis desta vez, não o script. Script agora é fonte de comandos, um parâmetro. As permissões de leitura sempre são definidas para todos os usuários, portanto, os shells as lerão.

    
por Sergiy Kolodyazhnyy 26.12.2015 / 13:06
3

Em geral, sh , ash , dash , bash , csh , tcsh , zsh ... são todos shells com suas próprias sintaxes e características. Existem algumas compatibilidades, mas elas são orientadas [ 1 ] : um bash shell executará um script sh , mas não é dito que o vice-versa . Uma invocação de sh exigiu menos recursos do que bash one. Para uma única instância, não é um problema, para milhares, deveria ser.

Formas de executar.
Para executar um arquivo como um programa no Linux, tanto se for um script quanto um compilado, deve-se definir o executar bit [ 2 ] e deve ser incluído em um dos diretórios de seu $PATH .

Se for um script, ele pode ser passado como argumento para o shell relativo ( sh , bash ... myfile.whatever ): se for passado para o shell errado você pode obter um comportamento incorreto e se tiver sorte com um erro ; neste caso, não precisa ser executável porque é como se você estivesse escrevendo as linhas escritas dentro do script diretamente no novo shell que você está invocando. Para executar no mesmo shell, você pode usar source myfile ou . myfile que são o equivalente para escrever linha por linha no shell atual o conteúdo do script.

Localização
Se o programa executável não estiver incluído no seu caminho, você deve especificar onde ele pode ser encontrado.

  • No seu caso, o ./ significa apenas o diretório atual do seu shell, assim como ~/myfile.whatever deve endereçar o arquivo myfile.whatever no diretório home ~/ .
  • Você pode invocá-lo de outro local, por exemplo, com /home/$USER/dir/myfile.whatever .
  • Se esse arquivo estiver dentro de um diretório incluído em seu caminho, você poderá invocá-lo com um simples myfile.whatever .

No caso de mais de um executável compartilhar o mesmo nome, a especificação do caminho completo será certa sobre qual deles você irá executar. which mycommand é capaz de dizer qual deles será executado agora (uma função, um alias, um construído ou o primeiro encontrado em seu caminho), mas não pode dizer qual deles será executado em um tempo futuro ou de outro usuário . Se você escrever expressamente o caminho completo, você corrigirá essa ambigüidade. É útil executar uma versão específica de um programa quando são instalados mais de um ao mesmo tempo ... e evitar o trojan. Em um script, sempre é sugerido escrever /bin/bash em vez de bash .

    
por Hastur 26.12.2015 / 13:56