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

18

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

O #!/bin/sh seria recomendado se a compatibilidade com todos os sistemas unix fosse um requisito absoluto?

No meu caso, o único sistema operacional que me interessa são o Ubuntu (Debian) e o OSX. Dado isso, eu poderia usar #!/bin/bash e ter certeza de que funcionaria em ambos os sistemas?
Isso também tornaria mais fácil usar scripts com sintaxe mais moderna e clara para comandos? O uso de #!/bin/sh também está relacionado ao uso do POSIX?

    
por Michael Durrant 04.02.2015 / 13:28

4 respostas

15

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

#!/usr/bin/env bash

isso invoca o que quer que bash seja configurado, não importa se é em /bin ou /usr/local/bin .

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

De qualquer forma, sim, o Bash permitiria que você usasse alguns recursos "modernos" que tornam sua vida mais fácil.

Por exemplo, os colchetes duplos:

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

Considerando que nos dialetos de conchas tradicionais você teria que recorrer a:

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

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

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

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

Estas são apenas algumas das coisas que o Bash lhe dá sobre a tradicional sintaxe comum do POSIX sh .

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

    
por 04.02.2015 / 13:48
10

No Debian e no Ubuntu, /bin/sh é dash , que é um shell compatível com POSIX. Se você especificar #!/bin/sh , deverá se limitar às instruções POSIX no seu script. (A vantagem é que dash começa mais rápido que bash , então seu script pode fazer seu trabalho em menos tempo.)

Em muitos (mais?) outros sistemas Linux, /bin/sh é bash , e é por isso que muitos scripts são escritos com #!/bin/sh como sua linha shebang, embora usem bash extensões.

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

No OS X /bin/bash também está disponível e /bin/sh é bash . A especificação de #!/bin/bash funcionará bem também.

    
por 04.02.2015 / 13:37
4

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

Note que, enquanto em muitos sistemas /bin/sh aponta para bash , em outros ele pode apontar para diferentes shells. É um link simbólico para dash no Debian e Ubuntu por exemplo. Além disso, mesmo se /bin/sh for um link para bash , o comportamento do shell mudará quando for chamado como sh (de man bash , emphasis mine):

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interac‐ tive login shell, or a non-interactive shell with the --login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The --noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is
defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the --rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, bash enters posix mode after the startup files are read.

    
por 04.02.2015 / 13:39
2

Se a compatibilidade com "todos os sistemas Unix" for um requisito absoluto - e se não for, por que você está escrevendo um script de shell? - então, sim, você deve estar usando #! /bin/sh , porque não é garantido que o Bash seja instalado em qualquer lugar , e muito menos em /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 congelam seus ambientes shell por volta de 1995. O que significa que você tem que usar coisas como o antiquado sort +N syntax - os sistemas mais recentes caíram! E também significa que não há funções shell, matrizes, [[ ... ]] , não ${foo#glob} , não $(( ... )) para aritmética, possivelmente nenhuma substituição de comando no estilo$( ... ), limites superiores pequenos e não documentados sobre o tamanho da entrada, ...

Provavelmente você pode se dar ao trabalho de não ter muita essa compatibilidade, mas se é um problema, recomendo que você considere uma linguagem menos terrível do que a shell. O interpretador básico do Perl é mais provável de estar disponível do que o Bash.

    
por 04.02.2015 / 15:46