Qual shell executa scripts quando não há uma 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 retornos ENOEXEC, de modo que o comportamento exato depende do programa que você executar um script como a partir .
- bash 4.2.39 - usa-se
- busybox-ash 1.20.2 - usa-se
- traço 0.5.7 - execuções / bin / sh
- fish 1.23.1 - reclama do ENOEXEC e culpa o arquivo errado
- AT&T ksh 93u + 2012.08.01 - usa-se
- mksh R40f - execuções / bin / sh
- pdksh 5.2.14 - execuções / bin / sh
- sh-heirloom 050706 - usa-se
- tcsh 6.18.01 - execuções / bin / sh
- zsh 5.0.0 - execuções / bin / sh
- cmd.exe 5.1.2600 - parece engraçado.
Na glibc , funciona execv()
ou execve()
simplesmente retorna ENOEXEC. Mas execvp()
oculta esse código de erro e chama automaticamente / bin / sh. (Isso está documentado em exec (3p) .)
O que é considerado "práticas recomendadas" em termos de escrita de scripts de shell que serão executados em qualquer plataforma? (ok, isso é meio que aberto)
Atenha-se a sh
e somente aos recursos definidos pelo POSIX ou apenas faça o bash completo (que está amplamente disponível) e mencione-o nos seus requisitos se for distribuí-lo.
(Agora que penso nisso, o Perl - ou talvez o Python - seria ainda mais portátil, sem mencionar uma sintaxe melhor.)
Sempre adicione a linha shebang. Se estiver usando o bash ou o zsh, use em #!/usr/bin/env bash
vez de codificar o caminho do shell. (No entanto, é garantido que o shell POSIX esteja em /bin/sh
, portanto, pule env
nesse caso.)
(Infelizmente, nem /bin/sh
sempre é o mesmo. O programa GNU autoconf precisa lidar com muitas peculiaridades .)
É 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 com intérprete incorreto: / bin / zsh: não existe esse arquivo ou diretório 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.
É possível escrever um script que execute 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 não recomendaria fazer isso por sua própria sanidade.