Geralmente, scripts shell conter o seguinte comentário na primeira linha do arquivo script: #!/bin/sh
. De acordo com as pesquisas que fiz, isso é chamado de "hash bang" e é um comentário convencional. Este comentário informa Unix que este arquivo é executado pela Shell Bourne sob o diretório /bin
.
Minha pergunta começa nesse ponto. Até agora eu não vi esse comentário como #!/bin/bash
. É sempre #!/bin/sh
. No entanto, as distribuições do Ubuntu não possuem o programa Bourne Shell. Eles têm o Bourne Again Shell (bash).
Nesse ponto, é correto colocar o comentário #!/bin/sh
em shell scripts escritos nas distribuições do Ubuntu?
shebang
Respostas:
#!/bin/sh
deve funcionar em todas as distribuições do Unix e do tipo Unix. Geralmente, é considerado o hashbang mais portátil, desde que o script seja mantido em conformidade com o POSIX. O/bin/sh
shell deve ser um shell que implementa o padrão de shell POSIX, independentemente do shell atual que se disfarça de/bin/sh
shell.#!/bin/sh
agora é normalmente apenas um link, já que o shell Bourne não é mais mantido. Em muitos sistemas Unix,/bin/sh
haverá um link para ,/bin/ksh
ou/bin/ash
, em muitos sistemas Linux baseados em RHEL, será um link/bin/bash
, no entanto, no Ubuntu e em muitos sistemas baseados no Debian, será um link/bin/dash
. Todos os shells, quando chamados comosh
, entrarão no modo de compatibilidade POSIX.O hashbang é um espaço reservado importante porque permite uma portabilidade muito maior do que outros métodos, desde que seu script seja estritamente compatível com POSIX (repetido para enfatizar a importância).
Nota: Quando
bash
é chamado no modo POSIX, ainda permite algumas coisas não POSIX[[
, como matrizes e muito mais. Essas coisas podem falhar em um não-bash
sistema.fonte
/bin/ash
.#! /
vez de apenas#!
.Você entendeu ao contrário.
/bin/sh
hoje em dia quase nunca é uma concha Bourne, e é quando é que você tem um problema ao usar um#! /bin/sh
estrondo.O shell Bourne foi um shell escrito no final dos anos 70 e substituiu o shell Thompson anterior (também chamado
sh
). No início dos anos 80, David Korn escreveu algumas extensões para o shell Bourne, corrigiu alguns bugs e projetou constrangimentos (e introduziu alguns) e o chamou de shell Korn.No início dos anos 90, o POSIX especificou o
sh
idioma com base em um subconjunto do shell Korn e a maioria dos sistemas agora mudou/bin/sh
para o shell Korn ou um shell compatível com essa especificação. No caso dos BSDs, eles mudaram gradualmente o seu/bin/sh
, inicialmente (depois que não podiam mais usar o shell Bourne por motivos de licença) o shell Almquist, um clone do shell Bourne com algumas extensões ksh para tornar-se compatível com POSIX.Hoje, todos os sistemas POSIX têm um shell chamado
sh
(na maioria das vezes, mas não necessariamente/bin
, o POSIX não especifica o caminho dos utilitários especificados) que é principalmente compatível com POSIX. Geralmente é baseado em ksh88, ksh93, pdksh, bash, ash ou zsh², mas não no shell Bourne, pois o shell Bourne nunca foi compatível com POSIX³. Algumas dessas conchas (bash
,zsh
,yash
e algunspdksh
derivados de permitir um modo compatível com POSIX quando invocada comosh
e são menos compatíveis em contrário).bash
(a resposta da GNU para o shell Korn) é na verdade o único shell de código aberto (e pode-se dizer que atualmente é mantido, pois os outros geralmente são baseados no ksh88, que não recebeu nenhum novo recurso desde os anos 90) que foi certificado como sendo compatível com POSIXsh
(como parte da certificação macOS).Quando você escreve um script com um
#! /bin/sh -
she-bang, deve usar umash
sintaxe padrão (e também deve usar a sintaxe padrão para os utilitários usados nesse script, se quiser ser portátil, não é apenas o shell que está envolvido na interpretação de um shell script), então não importa qual implementação dessesh
interpretador de sintaxe padrão seja usada (ksh
,bash
...).Não importa que essas cascas tenham extensões acima do padrão, desde que você não as utilize. É como escrever código C, desde que você escreva código C padrão e não use extensões de um compilador (como
gcc
) ou outro, seu código deve compilar OK, independentemente da implementação do compilador, desde que o compilador seja compatível.Aqui, com o seu
#! /bin/sh
she-bang, o seu principal problema seria os sistemas onde/bin/sh
é o shell Bourne que, por exemplo, não suporta características padrão, como$((1+1))
,$(cmd)
,${var#pattern}
... Em que caso você pode precisar de soluções alternativas como:A propósito, o Ubuntu
/bin/sh
não ébash
por padrão. Hoje emdash
dia, um shell baseado no NetBSDsh
, ele próprio baseado no shell Almquist, que é principalmente compatível com POSIX, exceto que ele não suporta caracteres de vários bytes. Em outros sistemas baseados em Debian Ubuntu e, você pode escolher entrebash
edash
para/bin/sh
comdpkg-reconfigure dash
) 4 .sh
Os scripts enviados com o Debian devem funcionar da mesma forma nos dois shells, à medida que são gravados no padrão de política Debian (um superconjunto do padrão POSIX). Você provavelmente vai descobrir que eles também trabalho OK emzsh
'ssh
emulação oubosh
(provavelmente nãoksh93
, nemyash
que não tem umlocal
builtin (exigido pela política Debian, mas não POSIX)).Todos os sistemas no escopo em unix.stackexchange.com possuem um POSIX em
sh
algum lugar. A maioria deles possui um/bin/sh
(você pode encontrar outros muito raros que não têm um/bin
diretório, mas provavelmente não se importa com isso), e isso geralmente é umsh
interpretador POSIX (e, em casos raros, um shell Bourne (não padrão) )Mas
sh
é o único executável de interpretador de shell que você pode encontrar em um sistema. Para os outros shells, você pode ter certeza de que o macOS, Cygwin e a maioria das distribuições GNU / Linux terãobash
. Os sistemas operacionais derivados do SYSV (Solaris, AIX ...) geralmente terão o ksh88, possivelmente o ksh93. O OpenBSD, MirOS, terá um derivado pdksh. o macOS terázsh
. Mas fora disso, não haverá garantia. Não há garantia de que umbash
ou outro desses shells será instalado em/bin
ou em outro local (geralmente é encontrado nos/usr/local/bin
BSDs quando instalados, por exemplo). E, claro, nenhuma garantia da versão do shell que será instalada.Observe que o
#! /path/to/executable
não é uma convenção , é um recurso de todos os kernels do tipo Unix ( introduzidos no início dos anos 80 por Dennis Ritchie ) que permite executar arquivos arbitrários, especificando o caminho do intérprete na primeira linha, começando com#!
. Pode ser qualquer executável.Quando você executa um arquivo cuja primeira linha começa com
#! /some/file some-optional-arg
, o kernel acaba executando/some/file
comsome-optional-arg
, o caminho do script e os argumentos originais como argumentos. Você pode fazer essa primeira linha#! /bin/echo test
para ver o que está acontecendo:Quando você usa em
/bin/sh -
vez de/bin/echo test
, o kernel executa/bin/sh - ./myscript foo
,sh
interpreta o código de conteúdo armazenadomyscript
e ignora a primeira linha como um comentário (começa com#
).¹ Provavelmente, o único sistema hoje em que algum de nós se depara com um
/bin/sh
baseado no shell Bourne é o Solaris 10. O Solaris é um dos poucos Unices que decidiu manter um shell Bourne lá para compatibilidade com versões anteriores (o POSIXsh
linguagem não é totalmente compatível com versões anteriores do shell Bourne) e (pelo menos para implantações de desktop e servidor completo) têm o POSIX emsh
outro lugar (em/usr/xpg4/bin/sh
, com base no ksh88), mas isso mudou no Solaris 11, onde/bin/sh
agora é o ksh93. Os outros são quase extintos.² O
/bin/sh
MacOS / X costumava serzsh
, mas depois mudou parabash
. Não ézsh
o foco principal a ser usado como umash
implementação POSIX . Seush
modo é principalmente poder incorporar ou chamar o códigosource
POSIX ( )sh
noszsh
scripts³ Recentemente, a @schily estendeu o shell do OpenSolaris (base no shell do SVR4, baseado no shell Bourne) para se tornar compatível com POSIX, chamado,
bosh
mas não sei que ele ainda é usado em qualquer sistema. Junto comksh88
isso, é um segundo shell compatível com POSIX, com base no código do shell Bourne4 Nas versões mais antigas, você também pode usar
mksh
ou sualksh
encarnação mais POSIX . Esse é o shell do MirOS (anteriormente MirBSD) baseado no pdksh, baseado no shell Forsyth (outra reimplementação do shell Bourne))fonte
exec sh "$0" "$@"
após definir oPATH
? Isso deveria pegarsh
no lugar correto, eu teria pensado.$PATH
.$(...)
modos emacs / vi, expansões til / brace (aquelas inicialmente do csh), fc, typeset, alias , sintaxe da função estilo ksh ...Sim, você pode usar
#!/bin/sh
em um script porque/bin/sh
(espero) é fornecido em tais sistemas, geralmente através de um link de algum tipo que faz com que sebash
comporte (mais ou menos) comosh
faria. Aqui está um sistema Centos7, por exemplo, vinculadosh
abash
:Você também pode usar
#!/bin/bash
se estiver escrevendo umbash
script apenas para esse sistema e quiser usar osbash
recursos. No entanto, esses scripts sofrerão problemas de portabilidade, por exemplo, no OpenBSD, ondebash
é instalado apenas se o administrador tiver o problema de instalá-lo (eu não) e, em seguida, ele estiver instalado/usr/local/bin/bash
, não/bin/bash
. Um#!/bin/sh
script estritamente POSIX deve ser mais portátil.fonte
sh
, o Bash entra no modo POSIX depois de ler os arquivos de inicialização". - gnu.org/software/bash/manual/bashref.html#Bash-POSIX-Mode#!/bin/bash
precisão para tirar proveito dos recursos que não são do POSIX./bin/sh
é um link simbólicobash
, está correto? Eu sei com certeza no CentOS que é.bash
. O binário sabe qual nome foi usado para invocá-lo e, quando é chamadosh
, age como o velho Bournesh
.Você perguntou
A resposta depende do que você escreve no script de shell.
Se você usar estritamente scripts portáteis compatíveis com POSIX e não usar nenhum comando específico do bash, poderá usá-lo
/bin/sh
.Se você sabe que você está sempre apenas usando o script em uma máquina com bash, e você quiser usar sintaxe específica do bash, então você deve usar
/bin/bash
Se você está quer ter certeza de que o script irá funcionar em uma variedade de máquinas Unix, então você deve usar somente a sintaxe compatível com POSIX, e
/bin/sh
Se você usa regularmente outro shell (por exemplo ksh , zsh ou tcsh ), e quer usar essa sintaxe em seu script, então você deve usar o interpretador apropriado (como
/bin/ksh93
,/bin/zsh
ou/bin/tcsh
)fonte
O "#!" O comentário nem sempre usa
/bin/bash
ou/bin/sh
. Ele apenas lista o que o intérprete deve ser, não apenas para scripts de shell. Por exemplo, meus scripts python geralmente começam com#!/usr/bin/env python
.Agora, a diferença entre
#!/bin/sh
e#!/bin/bash
é que isso/bin/sh
nem sempre é um link simbólico para/bin/bash
. Frequentemente, mas nem sempre. O Ubuntu é uma exceção notável aqui. Eu vi scripts funcionando bem no CentOS, mas falhando no Ubuntu porque o autor usou a sintaxe específica do bash#!/bin/sh
.fonte
Desculpe por derramar água fria em todas as ótimas respostas que dizem que
/bin/sh
está presente em todos os sistemas Unix - está presente, exceto no sistema Unix mais usado de todos os tempos: Android.O Android tem seu shell
/system/bin/sh
, e geralmente não há como fazer um/bin/sh
link, mesmo em um sistema enraizado (devido à maneira como o sistema é bloqueado pelo uso de selinux e de recursos (7) conjuntos delimitadores).Para aqueles que dirão que o Android não é compatível com POSIX: nem a maioria das distribuições Linux e BSD. E a existência de
/bin/sh
com esse caminho não é obrigatória pelo padrão :fonte
getconf
? Por exemplo, no Solaris 11.4, seria esse/usr/bin
? Aquele em/usr/xpg4/bin
(para conformidade com o SUSv2), aquele em/usr/xpg6/bin
(para conformidade com o SUSv3)?/usr/xpg7/bin
(para SUSv4)?/bin/sh