Existe alguma razão para ter um shebang apontando para / bin / sh em vez de / bin / bash?

53

Na maioria dos scripts de shell que eu já vi (além dos que ainda não escrevi), notei que o shebang está definido como #!/bin/sh. Isso realmente não me surpreende em scripts mais antigos, mas também existe em scripts relativamente novos.

Existe alguma razão para preferir a /bin/shsubstituição /bin/bash, uma vez que bashé bastante onipresente e muitas vezes padrão em muitas máquinas Linux e BSD que remontam a mais de uma década?

Jules
fonte
23
É uma boa partícula para usar /bin/shse você não usar bashfunções específicas . Um dia você pode ter que usar uma das seu script em um sistema no qual não está instalado (servidor remoto, computador embutido ...)
Mathieu
11
em geral, você deve evitar fazer perguntas que se prestem a respostas baseadas em opiniões (que é a única maneira possível de que essa pergunta possa ser respondida - mas essa é apenas a minha opinião ) .
mikeserv
9
Acredito que é possível responder a essa pergunta sem envolver mera opinião, apontando para pelo menos duas organizações que abordaram exatamente isso ao longo de vários anos e analisando a história e os resultados. Com muitas leituras adicionais anexadas, para inicializar. ☺
JdeBP
3
@JulesMazur ...the answers so far are fairly subjective...Uma declaração "subjetiva" é essencialmente baseada em opinião por definição. /bin/bashsó deve ser usado quando o bash for explicitamente necessário. Em mais de 40 anos como desenvolvedor, muito antes bash, eu quase nunca precisava dele explicitamente , exceto nos testes. (Também me esforço para evitar extensões de shell, mas a maioria dos meus scripts é destinada à distribuição.) Muitos scripts na rede também devem ser usados ​​para uso amplo.
user2338816
2
@ user2338816 meu mal, eu quis dizer objetivo . Obrigado por seus pontos!
Jules

Respostas:

83
  1. Existem sistemas que não fazem o envio do bash por padrão (por exemplo, FreeBSD).
  2. Mesmo se o bash estiver instalado, ele pode não estar localizado /bin.
  3. A maioria dos scripts simples não requer bash.
  4. O uso do shell POSIX é mais portátil e os scripts serão executados em uma variedade maior de sistemas.
Marco
fonte
17
Outro motivo: geralmente / bin / sh é mais rápido que o bash, ou pelo menos carrega mais rápido (por ser menor).
Derobert
5
@derobert, /bin/shé mais rápido se não for bash, ainda existem alguns sistemas como OS / X ou RHEL onde /bin/shestá bash.
Stéphane Chazelas
11
Não. Alguns SOs vinculam, porque o bash é compatível com versões anteriores.
Sobrique
7
Muito poucos scripts de assumir que /bin/shé /bin/bash. A mudança do Ubuntu do bash para o dash quebrou todos eles.
atamanroman
19
@atamanroman: Os scripts estavam incorretos em primeiro lugar, eles deveriam ter usado #!/bin/bashse quisessem o Bash (nada de errado nisso!). A mudança foi feita principalmente no upstream no Debian. Melhorou a experiência do usuário, teve um impacto mensurável no tempo de inicialização do sistema. Também impactou positivamente a segurança, consulte "Shellshock".
Dietrich Epp
28

A maioria dos scripts de sistema (relacionados ao Debian: Ubuntu, Mint, etc.) Linux são escritos para serem executados no traço mais rápido, que é o padrão / bin / sh nesses sistemas. O motivo é duplo:

  • Velocidade do sistema. Um código menor de traço carrega mais rápido e também roda mais rápido. Com algum (pequeno?) Esforço adicional (custo) para programadores de shell scripts.

  • Segurança. Ter diversidade de conchas ajuda a resiliência a bugs. Os sistemas Debian geralmente não eram vulneráveis ​​ao shellshock porque o shell padrão não tinha essa vulnerabilidade.

O Bash é realmente o shell padrão para os usuários , pois é mais poderoso e possui muito mais elementos para facilitar a codificação. Também é o padrão shno Mac OS (o link de / bin / sh). No entanto, chamar bashcom o nome do link de shfaz com que seja iniciado como um shell compatível com posix.


fonte
2
Um conjunto mais limitado de ferramentas disponíveis de um shell mais simples torna a escrita do código mais difícil (evite qualquer guerra fanática nisso). É por isso que alguns usuários gostam do zsh, que tem ainda mais ferramentas disponíveis do que o bash. Eu gosto mais do Bash, pois é um equilíbrio entre os dois extremos.
4
@RobertL, muitas das facilidades adicionadas no ksh e adotadas pelo bash existem porque facilitam substancialmente o processo de gravação de scripts robustos e corretos. Sem as várias adições que permitem que a atribuição e a avaliação indiretas sejam executadas com segurança, por exemplo, pode-se encontrar usando eval, com a exposição de segurança correspondente; de forma semelhante, sem suporte embutido expressão regular, pode-se precisar de usar comandos externos (a uma perda de desempenho pesado) para combinar mesmo dentro de uma única linha, etc
Charles Duffy
11
@RuiFRibeiro, nada está estaticamente vinculado no Debian. O Dash é mais limitado, mas é limitado principalmente em recursos interativos (sem conclusão e tal), para que seja mais rápido para scripts.
Jan Hudec
21

Outros apontaram que as premissas da pergunta, que o shell Bourne Again é padrão e onipresente, estão totalmente erradas.

Além disso, existem realmente boas razões para usar algo diferente do shell Bourne Again para interpretar scripts de shell. Esses motivos motivaram o grande projeto do Ubuntu e do Debian, ao longo de vários anos, a remover bashisms e a executar o máximo de scripts de shell pela inicialização do sistema (que era um monte de scripts de shell com o System 5 rc) e a instalação / remoção de pacotes usa o Shell Debian Almquist em vez do shell Bourne Again.

Simplificando: o shell Bourne Again, cheio de recursos interativos, não é o interpretador de shell mais rápido para um script de shell compatível com POSIX. Portanto, se alguém puder fazer seus scripts de shell serem compatíveis com POSIX, interpretando-os com um programa mais leve, como o shell Debian Almquist, o sistema de alguém terá um desempenho melhor. (No final, o Debian teve que fazer pequenos ajustes no shell Almquist, para adicionar suporte a algumas construções de shell não POSIX que eram simplesmente muito profundas e amplamente incorporadas e úteis demais para se livrar.)

O resultado disso tudo foi um grande ganho no desempenho do bootstrap.

Portanto, existem duas classes distintas de shell a serem consideradas aqui:

  • Os shells com todos os recursos interativos chamativos, configurados como shells de logon interativo para usuários no banco de dados de contas.
  • Os shells que interpretam muitos scripts rapidamente, que são usados ​​como intérpretes de script pelos programas de script de shell.

Observe que falar sobre isso como "preferir /bin/sh" é simplista demais. O Debian realmente tinha pelo menos dois objetivos:

  1. Em face dos administradores que usam o shell Debian Almquist, o shell Z (no modo POSIX), o shell Bourne Again (no modo POSIX), o shell MirBSD Korn e outros como /bin/sh, havia…

    1. ... tornar os scripts o mais portável possível, para que mudar o que foi /bin/shmapeado não estrague as coisas; ou

    2. ... criar scripts não portáteis direcione explicitamente o programa de intérprete correto , em vez de simplesmente esperar esse /bin/shmapa para ele.

  2. Estava tornando o shell Debian Almquist o mapeamento padrão para o /bin/shinvés do Bourne Shell, de modo que os scripts que eram compatíveis com POSIX (ou, mais apropriadamente, com conformidade com o Manual de Políticas Debian) rodavam mais rapidamente.

E, é claro, quando alguém entra nisso, pode ir muito além; como considerar as vantagens e desvantagens da eficiência /bin/truee /usr/bin/clearser scripts de shell ou programas compilados. Mas isso está além do escopo desta resposta, felizmente. ☺

Nada disso é muito novo, nem mesmo específico do Unix, é claro. Antes da virada do século, escrevi e publiquei um intérprete de linha de comando que apresentava sabores "interativos" e "não interativos", explicando essa mesma divisão em seu documento e observando a diferença entre as variáveis ​​de ambiente COMSPECe OS2_SHELL. Da mesma forma, a discussão sobre remoção de bashisms no System V do Debian rce os scripts de instalação / remoção de pacotes remonta aos anos 90.

Leitura adicional

JdeBP
fonte
2
"No final, o Debian teve que fazer pequenos ajustes no shell Almquist, para adicionar suporte a algumas construções de shell não POSIX que eram simplesmente muito profundas e amplamente incorporadas e úteis demais para se livrar." - Qual dos seus muitos links tem informações sobre isso? Isso parece muito interessante. :)
Curinga
3
IMHO, o desempenho é apenas um motivador para levar as pessoas a concordar com as mudanças. O grande motivo inicial para a mudança foi que o bash continuava quebrando a compatibilidade com versões anteriores. Pessoalmente, tive que corrigir problemas do bash pelo menos três vezes na minha carreira, porque o script funcionaria em uma versão do bash, mas falhou em outra (geralmente acontece após a atualização do sistema operacional). Dash não é apenas um intérprete um pouco mais rápido. Também é muito mais estável em termos de comportamento.
slebetman
Eu estaria interessado se os comentários na Schily Bourne Shellpágina de manual, consulte schilytools.sourceforge.net/bosh.html, são adequados para permitir que as pessoas entendam como escrever um script portátil (que depende apenas Bourne Shell featuresde 1989). O que eu fiz foi mencionar todos os aprimoramentos que não estavam nos antigos Bourne Shells. BTW: Também estou interessado em conhecer uma lista de basismos em traço.
schily
8

Existe alguma razão para ter um shebang apontando para / bin / sh em vez de / bin / bash?

Sim. A excelente resposta de @ Marco descreve isso muito bem.

O que devo usar no meu shebang?

Ao escrever seus próprios scripts, você deve apontar o shebang para a coisa mais geral contra a qual você testou.

No meu sistema (Centos 6.6), shestá vinculado a bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Isso significa que eu sempre uso #!/bin/bashno meu shebang, a menos que tenha verificado que não tenho bashims no meu script.

Ao definir o shebang para #!/bin/shvocê, você promete que o script funcionará com todas as implementações de sh.

Essa é uma promessa muito maior do que dizer que o script funcionará com o bash.

Aqui está um exemplo de script que se comportará incorretamente, dependendo de qual shimplementação o sistema está usando:

#!/bin/sh
n=1
a=$((++n))
echo $n

Ao usar basho script, será impresso:

2

Ao usar dasho script, será impresso:

1

Se eu quiser usar #!/bin/sho que preciso fazer?

  • Verifique o script com checkbashisms- Observe que isso não encontrará todos os bashims. Não encontrou o basismo no meu script acima
  • Teste o script usando outra shimplementação. Normalmente testo com dash, no entanto, espero que alguns basismos ou traços ainda possam passar despercebidos.

A página DashAsBinSh no wiki do Ubuntu tem muitas informações interessantes.

sixtyfootersdude
fonte
6
"Ao escrever seus próprios scripts, você deve apontar o shebang para a coisa mais geral contra a qual você testou .... Ao definir o shebang como #! / Bin / sh, você promete que o script funcionará com todas as implementações de sh . " Ponto excelente . +1, e você me fez repensar como vou escrever minhas coisas para o futuro. Obrigado! :)
Curinga
2
Bem, nem todas as implementações de /bin/sh; apenas os compatíveis com POSIX.
Blacklight Shining
4

O único motivo restante para escrever um shell script, em vez de um script em uma linguagem mais poderosa e ergonômica, é se a portabilidade para sistemas legados com um conjunto desconhecido de software instalado é mais importante do que qualquer outro fator .

/bin/shé o único intérprete de script disponível em tudo o que se chama Unix. Mas em uma enorme quantidade de sistemas legados, /bin/she os utilitários associados nem mesmo são compatíveis com a especificação "shell and utilities" POSIX.1-1996, muito menos algo mais moderno. As ferramentas compatíveis com o padrão são um complemento opcional, instalado em /usr/xpg4ou em algum local não óbvio. 1 Os scripts para a linguagem shell do subconjunto portátil são ainda mais entediantes e propensos a erros do que os scripts para a linguagem shell POSIX. (Leia um configurescript gerado pelo Autoconf em algum momento, se você não acredita em mim. Apenas a configuração deve ser suficiente para convencê-lo.)

Porém, se você puder assumir que outro intérprete de script está instalado (por exemplo, Bash), poderá assumir que um intérprete está instalado para uma melhor linguagem de script . Perl, por exemplo, é mais provável que esteja disponível do que o Bash.

Portanto, você nunca deve escrever um #! /bin/bashscript, porque se essa é uma opção, um idioma melhor também é uma opção.

1 Por exemplo, o Solaris 10 e versões anteriores enviavam o shell Bourne original como /bin/sh. Fui informado de que o Solaris 11 o atualizou para ksh93.

zwol
fonte
3
Em qual idioma você escreverá um script para inicializar um sistema? Ou dentro de um roteador SOHO (sistemas embutidos limitados)? Ou no Android? Um shell estará disponível em todos esses casos. Perl não.
11
Existem algumas imprecisões sobre as partes relacionadas à Solaris da sua resposta. No Solaris 10 e mais antigo, não/bin/sh é POSIX.1-1996, mas na verdade um shell Bourne original da sintaxe pré-POSIX. Isso dificulta muito a execução dos scripts com esses lançamentos. Os scripts portáteis no Solaris usariam, o que não será muito portátil em outros sistemas operacionais. No Solaris mais recente, o Oracle Solaris 11 lançado pela primeira vez em 2011, é um moderno que está em conformidade com as especificações recentes do POSIX e possui muitas extensões modernas. #!/bin/sh#!/usr/xpg4/bin/sh/bin/shksh93
Jlliagre
11
@BinaryZebra: "Um shell" estará disponível, sim. Mas o bash não é necessariamente esse shell (em particular a maioria dos roteadores SOHO usa o ashque é fornecido com o busybox), e eu costumo pensar que o zwol está certo de que o perl está mais disponível do que o bash.
Ben Voigt
11
@BenVoigt Estou comentando esta frase "O único motivo restante para escrever um shell script". Ainda existem algumas instâncias que precisam de um shell para algumas tarefas (não todas). Esses foram alguns exemplos do topo da minha cabeça. OTOH Em sistemas com memória suficiente (quase todos nos padrões atuais) e energia suficiente, a instalação do Perl (ou Python ou ....) é bastante rápida e fácil. No entanto, não estou defendendo nenhum shell específico. Onde você leu isso no meu comentário?
2
Discordo totalmente de sua afirmação altamente opinativa e não-factual de que "se bashestiver disponível, então será uma linguagem melhor para que você nunca escreva nenhum bashcódigo". Além disso, como aponta @sixtyfootersdude, você deve sempre usar, a #!/bin/bashmenos que tenha testado se seu script funciona com qualquer shell POSIX.
Curinga
0

Você realmente deveria estar usando

#! /bin/env sh

ou

#! /bin/env bash

dessa forma, você invoca um dos shell pela maneira como eles são instalados nesse sistema.

Para ser super seguro ( por exemplo, em casos de reinicialização por usuário único), use o shcontrário bash.

Paul Evans
fonte
6
Desde esta resposta : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Isso provavelmente também se aplica a she bash.
Jules
12
Não, você não deve usar #!/bin/envnada em um script portátil. É perfeitamente razoável supor que /bin/shexiste e é um shell compatível com POSIX em funcionamento. Por outro lado, nenhum dos meus sistemas possui a /bin/env.
Blacklight Shining
Também é um bom argumento.
Jules
11
@ Blacklight Shining, é definitivamente errado assumir um shell compatível com POSIX /bin/sh. O POSIX não exige isso e define outras regras para obter um ambiente compatível com POSIX em uma plataforma certificada POSIX.
schily
4
/usr/bin/envnão está universalmente disponível ...
vonbrand 27/12/2015