scripts de shell ainda estão funcionando sem #! (linha sha-bang)

10

Eu sou novo no shell scripts e muitos livros já escreveram que usam a linha #! (Sha-bang) no início do script para chamar o intérprete. E isso invocará um novo shell para o script e fará a interpretação linha por linha. do meu script básico ainda está sendo executado sem a linha mágica.

então minhas perguntas são:

  • de onde meu script básico conseguiu o intérprete.
  • como o script consegue localizar o intérprete.

Agora, deixe-me falar sobre meu script básico, que contém apenas a seguinte linha:

eco "script básico sem as linhas mágicas"

user1678213
fonte
2
Veja stackoverflow.com/questions/7268437/…
jasonwryan 10/10/12

Respostas:

3

Se a linha mágica não for fornecida, um shell padrão será usado para executar o script. Esse shell padrão pode ser o Bourne shell (sh), que é o caso em alguns tipos, no entanto, em outros tipos, o shell padrão usado é o mesmo que o shell de login para executá-lo. A questão é: não deixe que o sistema decida o shell, sempre forneça o shell que você deseja na primeira linha.

Guru
fonte
1
sim .. pode ser que meu shell atual esteja invocando um shell padrão para o shell script que não tenha números mágicos.
user1678213
1
@ user1678213 Sim, é o seu shell (e não o kernel) que está fazendo isso.
Gilles 'SO- stop be evil'
1
Acredito que o POSIX exige que / bin / sh seja usado neste caso.
vonbrand
2
@ vonbrand Este é um equívoco comum. O POSIX não exige que o shell POSIX seja /bin/sh, apenas para ser o primeiro shexecutável encontrado ao explorar um PATH em conformidade.
Jlliagre
3
Isso está incorreto, nunca é o "shell de login" usado para executá-lo. O que pode acontecer, porém, é que o shell de chamada (se o script for chamado de um shell) pode ter um filho interpretando-o.
Stéphane Chazelas
8

Quando você executa um programa, o kernel verifica se é iniciado por alguma sequência de bytes mágicos . Se o arquivo executável começar #!, o kernel interpreta o restante da linha como um nome de intérprete. Se o arquivo executável começar com \177ELF(onde \177é o byte 127), ele carregará o arquivo como um executável ELF ; esse é o tipo normal na maioria dos sistemas unix atualmente.

Se o kernel não reconhecer o formato do arquivo, ele se recusará a executá-lo e retornará o erro ENOEXEC (erro de formato Exec). Quando o shell percebe isso, é necessário executar o programa como um script de shell.

Para testemunhar isso em ação, adicione alguns comandos ao seu script:

ps l $$
ls -l /proc/$$/exe
echo hello

(Isso é para Linux, ajuste para outros departamentos.) Em seguida, tente executar esse script a partir de vários shells. Você verá que alguns shells geram novas instâncias para executar o script (bash, ksh93), enquanto outros geram /bin/sh(dash, pdksh, zsh).

Gilles 'SO- parar de ser mau'
fonte
O que eu procuro com seu ls -lcomando? Isso: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash-? se sim, o que isso diz? Além disso, notei que estou SHELL=/bin/bashusando env, mas mudar isso não pareceu mudar o comportamento. Talvez não esteja relacionado?
Emanuel Berg
parece que você está mudando a variável do shell "SHELL". Se sim, então você está apenas alterando o valor da variável do shell SHELL.não irá alterar o seu shell.
user1678213
2
@EmanuelBerg Sim (eu deveria ter escrito ls -l /proc/$$/exe, de fato). Os exelinks apontam para o shell que está executando seu script. Ao executar seu script, você verá que é o bash que interpreta o script. Se você o executar, por exemplo, pdksh, ele será executado /bin/sh. Não conheço nenhum shell que use a SHELLvariável de ambiente ou o shell de login nessa circunstância.
Gilles 'SO- stop be evil' -
2
@ user1678213 Alterar o shell /etc/passwdaltera o que é executado quando você faz logon no SSH ou em um console de texto. Não muda qual shell pode executar scripts.
Gilles 'SO- stop be evil' -
2
@ user1678213 Verifiquei o que escrevi aqui executando testes. Nenhum dos shells que testei analisou /etc/passwdpara decidir qual shell usar; eles bifurcaram uma instância de si mesmos ou foram executados /bin/sh.
Gilles 'SO- stop be evil'
-2

Provavelmente é uma das três possibilidades a seguir:

  1. Você está chamando o script diretamente com o intérprete, IE: bash script.sh

  2. O nome do arquivo de script possui uma extensão .sh, que faz com que o sistema procure o programa padrão para esse tipo de arquivo

  3. O ambiente de shell que você está usando está executando o 'eco' por si só, pois só posso supor que o arquivo de script é executável. Se, por exemplo, você usará um shell bash e tiver um comando em seu arquivo que é usado apenas pelo ksh, verá que ele não funcionará.

Boa sorte!

Bizna
fonte
3
nem o chamei com bash nem com qualquer extensão.
user1678213
1
e o ambiente de shell não está executando, porque quando invoco o comando ps após chamar meu script. O comando ps mostra dois bash process.which significa que há dois bash em execução. é o meu login shell bash e o outro é o bash para o meu basic_script
user1678213
1
2: o kernel não fará nada assim. O Zsh pode fazê-lo, e o bash pode ser torcido para fazê-lo. 3: Sim, mas varia um pouco entre as conchas, veja minha resposta.
Gilles 'SO- stop be evil'