Acabei de começar a me aprofundar nos scripts de shell e sempre joguei meu script em um arquivo, marquei-o chmod +x
e pronto /path/to/script.sh
, e deixei qualquer intérprete padrão agir com ele, o que presumi ser zsh porque é isso que Eu usei para minha concha. Aparentemente, parece que é apenas /bin/sh
por padrão, mesmo se eu executar o script a partir de um prompt zsh, porque comecei a colocar coisas específicas do zsh em meus scripts e ele está falhando, a menos que eu execute o zsh /path/to/script.sh
.
Para ir direto ao ponto, aqui estão minhas perguntas:
- Qual shell executa scripts quando não há linha Shebang (
#!/path/to/shell
) no início? Presumo/bin/sh
mas não posso confirmar. - O que é considerado "melhores práticas" em termos de escrita de scripts de shell que serão executados em qualquer plataforma? (ok, isso é meio aberto)
É possível escrever um script que tente usar o zsh e volte ao bash se o zsh não estiver disponível? Eu tentei colocar duas linhas shebang, como abaixo, mas só dá erro
bad interpreter: /bin/zsh: no such file or directory
se eu tentar em uma máquina sem zsh.#!/bin/zsh
#!/bin/bash
Responder1
Qual shell executa scripts quando não há linha shebang (#!/path/to/shell) no início? Presumo /bin/sh mas não posso confirmar.
O kernel se recusa a executar tais scripts e retorna ENOEXEC, então o comportamento exato depende do programa em que você executa tal scriptde.
- bash 4.2.39 – usa a si mesmo
- busybox-ash 1.20.2 – usa a si mesmo
- traço 0.5.7 – executa /bin/sh
- fish 1.23.1 – reclama do ENOEXEC, depois culpa o arquivo errado
- AT&T ksh 93u+2012.08.01 – usa a si mesmo
- mksh R40f – executa /bin/sh
- pdksh 5.2.14 – executa /bin/sh
- sh-heirloom 050706 – usa a si mesmo
- tcsh 6.18.01 – executa /bin/sh
- zsh 5.0.0 – executa /bin/sh
- cmd.exe 5.1.2600 – olha para você de forma engraçada.
Emglibc, funções execv()
ou execve()
apenas retornar ENOEXEC. Mas execvp()
oculta esse código de erro e invoca automaticamente /bin/sh. (Isso está documentado emexecutivo(3p).)
O que é considerado "melhores práticas" em termos de escrita de scripts de shell que serão executados em qualquer plataforma? (ok, isso é meio aberto)
Atenha-se sh
apenas aos recursos definidos pelo POSIX ou simplesmente vá completofesta(que está amplamente disponível) e mencione-o em seus requisitos se for distribuí-lo.
(Agora que penso nisso, Perl – ou talvez Python – seria ainda mais portátil, sem mencionar que teria uma sintaxe melhor.)
Sempreadicione a linha shebang. Se estiver usando bash ou zsh, use #!/usr/bin/env bash
em vez de codificar o caminho do shell. (No entanto, é garantido que o shell POSIX esteja em /bin/sh
, portanto pule env
nesse caso.)
(Infelizmente, /bin/sh
nem sempre é o mesmo. O GNUautoconfprograma tem que lidar commuitas peculiaridades diferentes.)
É possível escrever um script que tente usar o zsh e volte ao bash se o zsh não estiver disponível? Eu tentei colocar duas linhas Shebang, como abaixo, mas apenas erros comintérprete ruim: /bin/zsh: arquivo ou diretório inexistentefora se eu tentar em uma máquina sem zsh.
Só pode haver uma linha shebang; tudo depois do caractere de nova linha nem é lido pelo kernel e tratado como um comentário pelos shells.
Isso épossívelpara escrever um script que seja executado como #!/bin/sh
, verifique qual shell está disponível e execute exec zsh "$0" "$@"
ou exec bash "$0" "$@"
dependendo do resultado. No entanto, a sintaxe usada pelo bash e pelo zsh é tão diferente em vários lugares que eu gostarianão recomendo fazer issopara sua própria sanidade.
Responder2
1) O shell atual em que você está executando. (qualquer que seja o shell)
2) Fique com o mesmo tipo de shell (bash/dash/ash/csh/qualquer que seja seu tipo) e certifique-se de que suas "plataformas suportadas" instalem o shell que você deseja usar por padrão. Além disso, tente usar comandos comumente disponíveis nos sistemas. Evite opções específicas da máquina.
3) Não existe realmente uma lógica "se-então-senão" para o arquivo interpreter directive
. Você deve especificar um shell que deve existir em todos os sistemas que você deseja suportar... ou seja, #!/bin/bash
ou especificar um genérico, #!/bin/sh
desde que seu script seja bastante genérico em todos os shells.