Use #! / Bin / sh ou #! / Bin / bash para compatibilidade com Ubuntu-OSX e facilidade de uso e POSIX

18

Eu sei que posso usar como a primeira linha de scripts para invocar o shell desejado.

Seria #!/bin/shrecomendado se a compatibilidade com todos os sistemas unix fosse um requisito absoluto?

No meu caso, os únicos sistemas operacionais com os quais me preocupo são o Ubuntu (Debian) e o OSX. Dado isso, eu poderia usar #!/bin/bashe ter certeza de que funcionaria nos dois sistemas?
Isso também tornaria mais fácil o uso de scripts com sintaxe mais moderna e clara para comandos? O uso #!/bin/shtambém está relacionado ao uso do POSIX?

Michael Durrant
fonte
11
Provavelmente vale a pena notar que muitas distros começaram a se fundir /bine /usr/bin. Consequentemente, provavelmente é melhor usar #!/usr/bin/env <shname>a portabilidade hoje em dia.
precisa saber é o seguinte

Respostas:

15

Para iniciantes, se você puder supor que o Bash esteja pré-instalado (que, pelo que sei é o caso em todos os sistemas listados), use o seguinte hashbang para ser compatível:

#!/usr/bin/env bash

isso chama o que quer bashque esteja configurado, não importa se está dentro /binou /usr/local/bin.

Enquanto na maioria dos sistemas em uma ampla variedade (incluindo AIX, Solaris, vários tipos de BSD), bashacabavam em locais diferentes, envsempre terminavam em /usr/bin/env. O truque, no entanto, não é meu, mas do autor do Bash Cookbook.

De qualquer forma, sim, o Bash permitirá que você use alguns recursos "modernos" que facilitam sua vida.

Por exemplo, os colchetes duplos:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

enquanto nos dialetos shell tradicionais você teria que recorrer a:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

mas o melhor dos colchetes duplos é que eles permitem expressões regulares para correspondência. O Bash Hackers Wiki lhe dará muitos truques nessa direção.

Você também pode usar expressões bastante convenientes, como $((2**10))outras expressões aritméticas, alinhadas com a $((expression))sintaxe.

Usar backticks para subshells é bom, embora um pouco desatualizado. Mas os recursos de aninhamento de $(command ...)invocações são muito mais convenientes, pois você não precisará escapar de muitas coisas em diferentes níveis de subcamadas.

Essas são apenas algumas das coisas que o Bash fornece sobre a shsintaxe POSIX comum tradicional .

Mas se você quiser mais poder no shell (não apenas nos scripts), também dê uma olhada zsh.

0xC0000022L
fonte
O Bash é uma ferramenta muito útil, mas tome cuidado para não usá-lo para iniciar serviços que possam estar vulneráveis ​​a um bug de script do Bash, por exemplo, access.redhat.com/security/cve/CVE-2014-6271 . Atenha-se a shessas tarefas.
Rick-777
11
Rick-777: essa vulnerabilidade foi amplamente exagerada e, na minha opinião, seu comentário é FUD. Se um serviço do sistema é executado no bash, ele não é vulnerável a esse bug. Ele só é vulnerável a esse bug se iniciar um processo do bash enquanto permitir que usuários remotos acessem diretamente uma ou mais variáveis ​​de ambiente, como no FastCGI, e mesmo assim apenas em versões sem patches do bash. Em sistemas shvinculados a bash, a vulnerabilidade não será atenuada pelo uso sh.
Score_Und
11

No Debian e no Ubuntu, /bin/shis dash, que é um shell compatível com POSIX. Se você especificar #!/bin/sh, deverá limitar-se às instruções POSIX em seu script. (A vantagem é que dashcomeça mais rápido que bash, para que seu script possa ser executado em menos tempo.)

Em muitos (a maioria?) De outros sistemas Linux, /bin/shé bashpor isso que muitos scripts são escritos com #!/bin/shsua linha shebang, mesmo usando bashextensões.

Se você deseja usar bashextensões, a abordagem mais segura em todos os sistemas é especificar #!/bin/bash; dessa forma, você está explicitamente declarando sua dependência bash. Você precisa fazer isso no Debian e no Ubuntu. Como um bônus adicional, quando iniciado como /bin/sh bashdesativa algumas extensões (consulte a descrição do bashmodo POSIX para obter detalhes); portanto, #!/bin/bashé necessário especificar para obter todos os benefícios bash.

No OS X também /bin/bashestá disponível e /bin/shestá bash. A especificação #!/bin/bashtambém funcionará bem lá.

Stephen Kitt
fonte
5

Sim, o OSX e o Linux virão /bin/bash. Você deveria estar perfeitamente seguro. No entanto, isso não é POSIX. O shell POSIX está presente na /bin/shmaioria dos sistemas (todos?) E essa é a abordagem mais portátil e a única maneira de ser compatível com POSIX.

Observe que enquanto em muitos sistemas /bin/shaponta para bash, em outros, pode apontar para diferentes shells. É um link simbólico para o dashDebian e Ubuntu, por exemplo. Além disso, mesmo que /bin/shhaja um link para bash, o comportamento do shell muda quando é chamado como sh(de man bash, ênfase minha):

Se o bash for chamado com o nome sh, ele tentará imitar o comportamento de inicialização das versões históricas do sh o mais próximo possível, além de estar em conformidade com o padrão POSIX. Quando invocado como um shell de logon interativo, ou um shell não interativo com a opção --login, ele primeiro tenta ler e executar comandos de / etc / profile e ~ / .profile, nessa ordem. A opção --noprofile pode ser usada para inibir esse comportamento. Quando invocado como um shell interativo com o nome sh, o bash procura a variável ENV, expande seu valor se for
definido e usa o valor expandido como o nome de um arquivo para ler e executar. Como um shell chamado sh não tenta ler e executar comandos de outros arquivos de inicialização, a opção --rcfile não tem efeito. Um shell não interativo chamado com o nome sh não tenta ler outros arquivos de inicialização. Quando chamado como sh, o bash entra no modo posix após a leitura dos arquivos de inicialização.

terdon
fonte
2

Se a compatibilidade com "todos os sistemas Unix" é um requisito absoluto - e, se não, por que você está escrevendo um shell script? - então, sim, você deve estar usando #! /bin/sh, porque não é garantido que o Bash seja instalado em qualquer lugar , muito menos dentro /bin.

Na verdade, é muito, muito pior que isso. Se você precisa de compatibilidade com todos os sistemas Unix, isso inclui coisas como Solaris e AIX que congelaram seus ambientes de shell por volta de 1995. O que significa que você precisa usar coisas como a sort +Nsintaxe antiquada - que os sistemas mais novos caíram! E isso também significa que não há funções de shell, sem matrizes, não [[ ... ]], não ${foo#glob}, não $(( ... ))para $( ... )substituição aritmética, possivelmente sem estilo de comando, limites superiores pequenos e não documentados sobre o tamanho da entrada, ...

Você pode provavelmente começar afastado com não se preocupar com que tanto a compatibilidade, mas se ele é mesmo um problema, em primeiro lugar, eu recomendo fortemente que você considere uma linguagem que é menos terrível do que shell. É mais provável que o intérprete básico de Perl esteja disponível que o Bash.

zwol
fonte
Obrigado. Como declarado originalmente "No meu caso, os únicos SOs com os quais me preocupo são o Ubuntu (Debian) e OSX.". Esses são os únicos 2 sistemas que usei (e os utilizo bastante) nos últimos 5 anos, e é por isso que estou escrevendo um shell script que funcionaria apenas neles. Não preciso de um script universal e das limitações que ele apresentaria.
Michael Durrant
@MichaelDurrant Nesse caso, você não precisa, e não deve, escrever um script de shell. Em vez disso, você deve usar qualquer uma das inúmeras linguagens de script melhores que são uma opção quando você não precisa de portabilidade total.
Zwol 6/02