Qual é o shebang Bash preferido?

1132

Existe alguma coisa Bashobjetivamente melhor do que as outras para a maioria dos usos?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -
  • etc

Lembro-me vagamente há muito tempo de ouvir que adicionar um traço ao final impede que alguém passe um comando para o seu script, mas não consegue encontrar detalhes sobre isso.

Kurtosis
fonte
4
E é /usr/local/bin/bashno OpenBSD.
JWW

Respostas:

1536

Você deve usar #!/usr/bin/env bashpara portabilidade : diferentes * nixes são colocados bashem lugares diferentes, e usar /usr/bin/envé uma solução alternativa para executar o primeiro bashencontrado no PATH. E shnão ébash .

l0b0
fonte
9
Obrigado. Também parece que adicionar - ao final de $! / Usr / bin / env bash - não fará nada, pois apenas um argumento é permitido por * nix no shebang, e isso é usado por 'bash'. Aparentemente, isso é útil apenas para impedir que argumentos maliciosos sejam transmitidos para o script na linha de comando se o shebang do script for um dos outros sem argumentos ( /bin/sh, etc).
Kurtosis
13
O @Ray bashnão vive em /bintodos os sistemas.
ptierno
12
O mesmo para mim, apenas o adicionei a um pseudônimo: alias shebang='echo "#!/usr/bin/env bash"'agora eu só tenho que abrir o terminal e digitar shebang em vez de ir aqui.
Oylex
19
Esta resposta é enganosa. O POSIX não diz que envestá em /usr/bin/env. Poderia estar no local /bin/envou em qualquer lugar, desde que esteja no caminho. Poderia ser em /dummy/envcaso /dummyestá em PATH. O Shebang em si é indefinido no POSIX, para que eu possa #!stop toasteriniciar a máquina de café USB e ser compatível com POSIX. Portanto, #!/usr/bin/env bashnão é particularmente melhor do que #!/bin/bash, poderia ser menos portátil, dependendo.
darkfeline
19
@darkfeline A portabilidade não é absoluta - é matematicamente impossível criar qualquer script que faça a mesma coisa em todas as plataformas. De 2012 a 2018, /usr/bin/envexistem em mais máquinas do que em qualquer um dos /bin/bashxor /usr/bin/bash, portanto, um script que começa com essa linha fará o esperado em tantas máquinas quanto possível.
L0b0
80

/bin/shgeralmente é um link para o shell padrão do sistema, que geralmente é ativado bash, por exemplo, sistemas Debian é o peso mais leve dash. De qualquer forma, o shell Bourne original é sh, portanto, se o seu script usa alguns bashrecursos específicos (2ª geração, "Bourne Again sh") ( [[ ]]testes, matrizes, várias coisas açucaradas, etc.), você deve ser mais específico e usar o posterior . Dessa forma, em sistemas em que o bash não está instalado, seu script não será executado. Entendo que pode haver uma emocionante trilogia de filmes sobre essa evolução ... mas isso pode ser um boato.

Observe também que, quando evocado como sh, bashaté certo ponto se comporta como padrão POSIX sh (consulte também a documentação do GNU sobre isso).

delicadoLatticFever
fonte
2
O Public Domain Korn Shell (pdksh) é o padrão no OpenBSD.
JWW
A maioria dos sistemas não se vincula /bin/sha nenhum lugar, /usrpois isso dificultaria a execução dos scripts init antes da /usrmontagem.
aij
@aij Eu não sei por que eu coloquei "muitos ou a maioria" não - eu sou um usuário fedora, onde /bine /sbindurante anos ter sido apenas links simbólicos, por padrão, para /usr/bine /usr/sbin, por isso, nesse contexto, /bin/shé um link para bashe o real diretório é /usr/bin. Mas eu vou corrigir o acima.
DelicadoLatticeworkFever
44

Eu recomendo usar:

#!/bin/bash

Não é 100% portátil (alguns sistemas são colocados bashem um local que não seja /bin), mas o fato de muitos scripts existentes #!/bin/bashpressionarem vários sistemas operacionais para fazer /bin/bashpelo menos um link simbólico para o local principal.

A alternativa de:

#!/usr/bin/env bash

foi sugerido - mas não há garantia de que o envcomando esteja /usr/bin(e eu usei sistemas onde não está). Além disso, este formulário usará a primeira instância de bashnos usuários atuais $PATH, que pode não ser uma versão adequada do shell bash.

(Mas /usr/bin/envdeve funcionar em qualquer sistema razoavelmente moderno, seja porque envestá dentro /usr/binou porque o sistema faz algo para fazê-lo funcionar. O sistema que me referi acima foi o SunOS 4, que provavelmente não uso há cerca de 25 anos.)

Se você precisar de um script para executar em um sistema que não possua /bin/bash, poderá modificá-lo para apontar para o local correto (isso é reconhecidamente inconveniente).

Eu discuti as compensações em maior profundidade na minha resposta a esta pergunta .

Uma atualização um tanto obscura: um sistema que eu uso, o Termux , uma camada semelhante a um desktop Linux que roda no Android, não possui /bin/bash( bashé /data/data/com.termux/files/usr/bin/bash) - mas possui um tratamento especial para oferecer suporte #!/bin/bash.

Keith Thompson
fonte
3
2 anos depois e este ainda é o melhor conselho aqui. Se a solução simples não funcionar, você deverá questionar suas decisões anteriores. A resposta aceito e mais upvoted não é errado, não é apenas certo :)
Engenheiro de Software
27

Usar uma linha shebang para chamar o intérprete apropriado não é apenas para o BASH. Você pode usar o shebang para qualquer linguagem interpretada em seu sistema, como Perl, Python, PHP (CLI) e muitas outras. A propósito, o shebang

#!/bin/sh -

(também pode ser de dois hífens, ie --) termina as opções do bash que depois serão tratadas como nomes de arquivos e argumentos.

O uso do envcomando torna seu script portátil e permite configurar ambientes personalizados para o seu script, portanto, os scripts portáteis devem usar

#!/usr/bin/env bash

Ou para qualquer idioma como o Perl

#!/usr/bin/env perl

Não deixe de procurar nas manpáginas bash:

man bash

e env:

man env

Nota: Nos sistemas Debian e baseados em Debian, como o Ubuntu, shestá vinculado a dashnão bash. Como todos os scripts do sistema usam sh. Isso permite que o bash cresça e o sistema permaneça estável, de acordo com o Debian.

Além disso, para manter a invocação * nix como se eu nunca usasse extensões de arquivo em scripts invocados shebang, pois você não pode omitir a extensão na invocação em executáveis ​​como no Windows. O comando file pode identificá-lo como um script.

Jamie R Robillard Sr.
fonte
4

Realmente depende de como você escreve seus scripts bash. Se você /bin/shtiver o link simbólico para o bash, quando o bash for chamado como sh, alguns recursos não estarão disponíveis .

Se você deseja recursos específicos do bash e não POSIX, use #!/bin/bash

Glenn Jackman
fonte
3
O Bash não está instalado no OpenBSD. Se você instalá-lo via pkg_add, ele estará localizado em /usr/local/bin, o que pode não estar no caminho.
JWW
que tal um POSIXrecurso?
Nikolan Asad