O que significa ser “sh compatível”?

63

Eu vi a frase "compatível com sh" usada geralmente em referência a conchas. Não tenho certeza se isso também se aplica aos programas que podem ser executados a partir de shells.

O que significa um shell ou outro programa ser "compatível com sh"? O que significaria ser "sh incompatible"?

Edit: Esta pergunta que faz a diferença entre bash e sh é muito relevante: Diferença entre sh e bash

Eu ainda gostaria de uma resposta direta ao que significa ser "sh compatível". Uma expectativa razoável pode ser que "sh compatível" signifique "implementa a linguagem de comando do shell", mas por que existem tantos shells "compatíveis com sh" e por que são diferentes?

Praxeolitic
fonte
11
Para um script de shell, refere-se ao fato de esse script usar ou não sintaxe compatível (executável) com o Bourne Shell ( sh). Para um shell diferente, refere-se à possibilidade de executar ou não scripts de shell Bourne.
HalosGhost
Se você quer aprender inventor de conchas você pode visitar a minha resposta em unix.stackexchange.com/questions/45684/...
Golfo Pérsico

Respostas:

116

Por que existem tantas conchas "compatíveis com sh"?

O shell Bourne foi lançado pela primeira vez em 1979 como parte do Unix V7 . Como praticamente todos os sistemas Unix e similares ao Unix descendem do V7 Unix - mesmo que apenas espiritualmente -, o shell Bourne está conosco "para sempre".

O shell Bourne, na verdade, substituiu um shell anterior, retronomeou o shell Thompson , mas aconteceu tão cedo na história do Unix que hoje está praticamente esquecido. A concha Bourne é um superconjunto da concha Thompson

Ambos os cartuchos de Bourne e Thompson foram chamados sh. O shell especificado pelo POSIX também é chamado sh. Então, quando alguém diz que é shcompatível, está se referindo a essa série de cartuchos. Se eles quisessem ser específicos, diriam "shell POSIX" ou "shell Bourne". ³

O shell POSIX é baseado na versão de 1988, KornShell , que por sua vez foi concebido para substituir o shell Bourne no AT & T Unix, ultrapassando o shell C BSD em termos de features.⁴ Na medida em que kshé o antepassado do shell POSIX, a maioria Os sistemas Unix e Unix-like incluem algumas variantes do shell Korn atualmente. As exceções são geralmente pequenos sistemas embarcados, que não podem permitir o espaço que um shell POSIX completo ocupa.

Dito isto, o shell Korn - como algo distinto do shell POSIX - nunca se tornou realmente popular fora do mundo comercial do Unix. Isso ocorre porque seu crescimento correspondeu aos primeiros anos de comercialização do Unix, por isso foi pego nas guerras do Unix . O BSD Unixes o evitou em favor do shell C, e seu código-fonte não estava disponível gratuitamente para uso no Linux quando foi iniciado.⁵ Então, quando os primeiros distribuidores do Linux procuraram um shell de comando para acompanhar seu kernel Linux, eles geralmente escolhem o GNU Bash , um dos shcompatíveis de que você está falando.⁶

Essa associação inicial entre Linux e Bash praticamente selou o destino de muitos outros shells, incluindo ksh, cshe tcsh. Ainda existem pessoas obstinadas que usam essas conchas hoje em dia, mas são muito minoritárias.

Toda essa história explica por que os criadores de retardatários relativos gostam de bash, zshe yashoptaram por torná-los shcompatíveis: a compatibilidade com Bourne / POSIX é o mínimo que um shell para sistemas semelhantes a Unix deve fornecer para obter ampla adoção.

Em muitos sistemas, o shell de comando interativo padrão e /bin/shsão coisas diferentes. /bin/shtalvez:

  • O shell Bourne original. Isso é comum em sistemas UNIX® mais antigos, como o Solaris 10 (lançado em 2005) e seus antecessores.⁸

  • Um shell certificado pelo POSIX. Isso é comum em sistemas UNIX® mais recentes, como o Solaris 11 (2010).

  • A concha Almquist . Este é um clone de shell de código aberto Bourne / POSIX lançado originalmente na Usenet em 1989 , que depois contribuiu com o CSRG de Berkeley para inclusão na primeira versão do BSD que não contém código-fonte da AT&T, 4.4BSD-Lite . O shell Almquist é chamado frequentemente ash, mesmo quando instalado como /bin/sh.

    O 4.4BSD-Lite, por sua vez, tornou-se a base para todos os derivados modernos do BSD, /bin/shpermanecendo como um derivado Almquist na maioria deles, com uma grande exceção observada abaixo. Você pode ver essa descendência direta nos repositórios de código-fonte do NetBSD e FreeBSD : eles estavam enviando um derivado do shell Almquist desde o primeiro dia.

    Existem dois ashgarfos importantes fora do mundo do BSD:

    1. dash, adotado pelo Debian e Ubuntu em 2006 como a /bin/shimplementação padrão . (O Bash continua sendo o shell de comando interativo padrão nos derivados do Debian.)

    2. O ashcomando no BusyBox , que é freqüentemente usado em Linuxs embarcados e pode ser usado para implementar /bin/sh. Desde que ele é pós-datado dashe foi derivado do ashpacote antigo do Debian , eu escolhi considerá-lo um derivado de, dashe não ash, apesar do nome do comando no BusyBox.

      (O BusyBox também inclui uma alternativa menos funcional ao ashchamado hush. Normalmente, apenas um dos dois será incorporado a qualquer dado binário do BusyBox: ashpor padrão, mas hushquando o espaço é muito /bin/shpequeno . Assim, em sistemas baseados no BusyBox nem sempre é dashparecido.)

  • GNU Bash , que desativa a maioria de suas extensões não POSIX quando chamado comosh .

    Essa escolha é típica nas variantes de desktop e servidor do Linux, exceto o Debian e seus derivados. O Mac OS X também faz isso desde o Panther, lançado em 2003.

  • Um shell com ksh93extensões POSIX , como no OpenBSD . Embora o shell do OpenBSD mude o comportamento para evitar incompatibilidades de sintaxe e semântica com os shells Bourne e POSIX quando chamado sh, ele não desabilita nenhuma de suas extensões puras, sendo aquelas que não conflitam com os shells mais antigos.

    Isso não é comum; você não deve esperar ksh93recursos /bin/sh.

Eu usei "shell script" acima como um termo genérico que significa script de shell Bourne / POSIX. Isso se deve à onipresença das conchas da família Bourne. Para falar sobre scripts em outros shells, você precisa fornecer um qualificador, como "C shell script". Mesmo nos sistemas em que um shell da família C é o shell interativo padrão, é melhor usar o shell Bourne para scripts.

É revelador que quando a Wikipedia classifica os shells do Unix , eles os agrupam em Bourne shell compatível, C shell compatível e "outros".

Este diagrama pode ajudar:

As conchas do Unix: famílias Shell Bourne, Korn, POSIX, C e rc

(Clique para a versão SVG, 31 kB, ou para ver a versão PNG em tamanho real , 218 kB.)

O que significaria ser "sh incompatible"?

Alguém falando sobre shalgo incompatível normalmente significa uma das três coisas:

  1. Eles estão se referindo a um desses "outros" shells.⁹

  2. Eles estão fazendo uma distinção entre as famílias Bourne e C shell.

  3. Eles estão falando sobre algum recurso específico em uma concha da família Bourne que não está em todas as outras conchas da família Bourne. ksh93,, bashe zshem particular, têm muitos recursos que não existem nos shells "padrão" mais antigos. Esses três também são incompatíveis entre si de várias maneiras, depois que você ultrapassa o POSIX / ksh88base compartilhado .

É um erro clássico escrever um script de shell com uma #!/bin/sh linha shebang na parte superior, mas usar as extensões de shell Bash ou Korn. Como /bin/shé um dos shells no diagrama da família Korn / POSIX acima em muitos sistemas hoje em dia, esses scripts funcionarão no sistema em que estão escritos, mas depois falharão nos sistemas, onde /bin/shé algo da família de shells Bourne mais ampla. A melhor prática é usar #!/bin/bashou #!/bin/kshmostrar linhas se o script usar essas extensões.

Existem várias maneiras de verificar se um determinado script do shell da família Bourne é portátil:

  • Execute checkbashismsnele, uma ferramenta do projeto Debian que verifica um script em busca de " basismos ".

  • Execute-o em poshum shell no repositório de pacotes Debian que propositalmente implementa apenas os recursos especificados pelo SUS3 , além de alguns outros recursos menores .

  • Executá-lo sob osha partir do projeto Ferramentas Schily , uma versão melhorada do Bourne shell como software livre pela Sun como parte do OpenSolaris em 2005, tornando-se uma das maneiras mais fáceis de obter um estilo de 1979 Bourne shell em um computador moderno.

    A distribuição do Schily Tools também inclui boshum shell do tipo POSIX com muitos recursos fora do padrão , mas que pode ser útil para testar a compatibilidade de scripts de shell destinados a serem executados em todos os shells da família POSIX. Ele tende a ser mais conservadora no seu conjunto de recursos de bash, zshe as versões melhoradas dos ksh93.

    O Schily Tools também inclui um shell chamado bsh, mas essa é uma singularidade histórica que não é um shell da família Bourne.

  • Veja o capítulo sobre programação portátil do shell no manual GNU Autoconf . Você pode reconhecer algumas das construções problemáticas mencionadas em seus scripts.

Por que eles são diferentes?

Pelas mesmas razões, todos os "Novos e aprimorados!" as coisas são diferentes:

  • A versão aprimorada só poderia ser aprimorada quebrando a compatibilidade com versões anteriores.

  • Alguém pensou em uma maneira diferente de algo funcionar, do que eles gostam mais, mas que não é da mesma maneira que o antigo funcionava.

  • Alguém tentou reimplementar um padrão antigo sem entendê-lo completamente, por isso estragou tudo e criou uma diferença não intencional.


Notas de rodapé e apartes :

  1. As primeiras versões do BSD Unix eram apenas coleções de software complementares para o V6 Unix. Como o shell Bourne não foi adicionado ao AT&T Unix até a V7, o BSD tecnicamente não começou com o shell Bourne. A resposta de BSD à natureza primitiva do shell Thompson foi o shell C .

    No entanto, as primeiras versões independentes de BSD (2.9BSD e 3BSD) foram baseadas em V7 ou seu sucessor portátil UNIX / 32V , então eles fizeram incluir o shell Bourne.

    (A linha 2BSD se transformou em um garfo paralelo de BSD para da Digital minicomputadores PDP , enquanto as linhas 3BSD e 4BSD passou a tirar proveito de tipos de computadores mais recentes, como Vaxen e estações de trabalho UNIX 2.9BSD era essencialmente a versão PDP de 4.1cBSD;. Fossem contemporânea, e código compartilhado . PDPs não simplesmente desaparecer quando o VAX chegou, para que a linha 2BSD é ainda bamboleando ao longo ).

    É seguro dizer que o shell Bourne estava presente em todo o mundo Unix em 1983. Essa é uma boa aproximação de "para sempre" na indústria de computação. O MS-DOS obteve um sistema de arquivos hierárquico naquele ano (awww, que delícia!) E o primeiro Macintosh de 24 bits com sua tela de 9 "em preto e branco - não em escala de cinza, literalmente em preto e branco - não seria lançado até o início do próximo ano.

  2. O shell Thompson era bastante primitivo para os padrões de hoje. Era apenas um shell de comando interativo, em vez do ambiente de programação de scripts que esperamos hoje. Ele tinha coisas como pipes e redirecionamento de E / S, que consideramos prototipicamente parte de um "shell Unix", de modo que pensamos no shell de comando do MS-DOS como obtê-los do Unix.

    O shell Bourne também substituiu o shell PWB , que adicionou coisas importantes ao shell Thompson, como programabilidade ( if, switche while) e uma forma inicial de variáveis ​​de ambiente. O shell PWB é ainda menos lembrado que o shell Thompson, pois não fazia parte de todas as versões do Unix.

  3. Quando alguém não é específico sobre a compatibilidade de shell POSIX x Bourne, há várias coisas que eles podem significar.

    Em um extremo, eles poderiam estar usando o shell Bourne de 1979 como linha de base. Um " shroteiro -compatível" neste sentido significaria espera-se para executar perfeitamente no shell Bourne verdadeira ou qualquer dos seus sucessores e clones: ash, bash, ksh, zsh, etc.

    Alguém no outro extremo assume o shell especificado pelo POSIX como uma linha de base. Tomamos tantos recursos do shell POSIX como "padrão" hoje em dia que muitas vezes esquecemos que eles não estavam realmente presentes no shell Bourne: aritmética integrada, controle de tarefas, histórico de comandos, aliases, edição de linha de comando, a $()forma de comando substituição etc.

  4. Embora o shell Korn tenha raízes desde o início dos anos 80, a AT&T não o lançou no Unix até o System V, versão 4, em 1988. Como muitos Unixes comerciais são baseados no SVR4, isso inclui kshpraticamente todos os Unix comerciais relevantes do final dos anos 80 em diante.

    (Alguns sabores estranhos do Unix baseados em SVR3 e anteriores mantiveram partes do mercado após o lançamento do SVR4, mas foram os primeiros contra a parede quando a revolução veio).

    1988 é também o ano em que o primeiro padrão POSIX foi lançado, com seu "POSIX shell" baseado em shell Korn. Mais tarde, em 1993, uma versão aprimorada do shell Korn foi lançada. Desde que o POSIX efetivamente pregou o original, foi kshdividido em duas versões principais: ksh88e ksh93, nomeado após os anos envolvidos em sua divisão.

    ksh88não é totalmente compatível com POSIX, embora as diferenças sejam pequenas, de modo que algumas versões do ksh88shell foram corrigidas para serem compatíveis com POSIX. (Isso de uma interessante entrevista no Slashdot com o Dr. David G. Korn . Sim, o cara que escreveu o shell.)

    ksh93é um superconjunto totalmente compatível do shell POSIX . O desenvolvimento ksh93foi esporádico desde que o repositório de origem primário foi transferido da AT&T para o GitHub, com a versão mais recente com cerca de 3 anos de idade, enquanto escrevo isso, ksh93v. (O nome base do projeto permanece ksh93com sufixos adicionados para indicar versões de lançamento além de 1993.)

    Os sistemas que incluem um shell Korn como algo separado do shell POSIX geralmente o tornam disponível /bin/ksh, embora às vezes ele esteja oculto em outro lugar.

    Quando falamos sobre kshou o shell Korn por nome, estamos falando de ksh93recursos que o distinguem de seus subconjuntos de shell Bourne e POSIX compatíveis com versões anteriores. Você raramente encontra os puros ksh88hoje.

  5. A AT&T manteve o código-fonte do shell Korn como proprietário até março de 2000 . Nesse ponto, a associação do Linux ao GNU Bash era muito forte. O Bash e ksh93 cada um têm vantagens em relação ao outro , mas, neste momento, a inércia mantém o Linux fortemente associado ao Bash.

    Quanto ao motivo pelo qual os primeiros fornecedores de Linux costumam escolher o GNU Bash pdksh, que estava disponível no momento em que o Linux era iniciado, eu acho que é porque grande parte do restante da área de usuários também veio do projeto GNU . O Bash também é um pouco mais avançado que pdksh, já que os desenvolvedores do Bash não se limitam a copiar os recursos do shell Korn.

    O trabalho pdkshparou no momento em que a AT&T lançou o código-fonte para o verdadeiro shell Korn. Existem dois garfos principais que ainda são mantidos: o OpenBSD pdksheo MirBSD Korn Shellmksh ,.

    Acho interessante que mkshseja a única implementação de shell Korn atualmente empacotada para Cygwin.

  6. O GNU Bash vai além do POSIX de várias maneiras, mas você pode solicitar que ele execute em um modo POSIX mais puro .

  7. csh/ tcshera geralmente o shell interativo padrão no BSD Unixes até o início dos anos 90.

    Por ser uma variante BSD , as versões anteriores do Mac OS X eram assim, através do Mac OS X 10.2 "Jaguar" . O OS X mudou o shell padrão tcshpara o Bash no OS X 10.3 "Panther" . Essa alteração não afetou os sistemas atualizados da versão 10.2 ou anterior. Os usuários existentes nesses sistemas convertidos mantiveram seu tcshshell.

    O FreeBSD afirma ainda usar tcshcomo shell padrão , mas na VM do FreeBSD 10 que tenho aqui, o shell padrão parece ser uma das variantes de shell Almquist compatíveis com POSIX . Isso também é verdade no NetBSD.

    O OpenBSD usa uma bifurcação pdkshcomo shell padrão.

    A maior popularidade do Linux e do OS X faz com que algumas pessoas desejem que o FreeBSD também mude para o Bash, mas não o farão tão cedo por razões filosóficas . É fácil trocá-lo , se isso o incomoda.

  8. É raro encontrar um sistema com uma casca Bourne verdadeiramente baunilha /bin/shnos dias de hoje. Você precisa fazer o possível para encontrar algo suficientemente próximo para testar a compatibilidade.

    Estou ciente de apenas uma maneira de executar um shell Bourne vintage genuíno de 1979 em um computador moderno: use as imagens de disco do Ancient Unix V7 com o simulador SIMH PDP-11 do Computer History Simulation Project . O SIMH roda em praticamente todos os computadores modernos , não apenas no Unix. O SIMH ainda roda no Android e no iOS .

    Com o OpenSolaris , a Sun forneceu pela primeira vez a versão SVR4 do shell Bourne. Antes disso, o código-fonte das versões pós-V7 do shell Bourne estava disponível apenas para aqueles com uma licença de código-fonte Unix.

    Agora esse código está disponível separadamente do restante do projeto OpenSolaris extinto, de várias fontes diferentes.

    A fonte mais direta é o projeto de shell Heirloom Bourne . Isso ficou disponível logo após o lançamento original do OpenSolaris em 2005. Alguns trabalhos de portabilidade e correção de bugs foram realizados nos próximos meses, mas o desenvolvimento do projeto foi interrompido.

    Jörg Schilling fez um trabalho melhor em manter uma versão desse código como oshem seu pacote Schily Tools . Veja acima para mais informações.

    Lembre-se de que esses shells derivados da versão de código-fonte de 2005 contêm suporte a conjuntos de caracteres de vários bytes , controle de tarefas, funções de shell e outros recursos não presentes no shell Bourne original de 1979.

    Uma maneira de saber se você está em um shell Bourne original é verificar se ele suporta um recurso não documentado adicionado para facilitar a transição do shell Thompson: ^como um alias para |. Ou seja, um comando como ls ^ moredará um erro em um shell do tipo Korn ou POSIX, mas se comportará como ls | moreem um shell Bourne verdadeiro.

  9. Ocasionalmente, você encontra um fish, scshou rc/esaderente, mas eles são ainda mais raros do que os ventiladores C shell.

    A rcfamília de shells não é comumente usada em sistemas Unix / Linux, mas a família é historicamente importante, e foi assim que ganhou um lugar no diagrama acima. rcé o shell padrão do Plan 9 do sistema operacional Bell Labs , um tipo de sucessor da 10ª edição do Unix , criado como parte da pesquisa contínua da Bell Labs em design de sistema operacional. É incompatível com os shell Bourne e C em um nível de programação; provavelmente há uma lição lá.

    A variante mais ativa rcparece ser a mantida por Toby Goodwin , que é baseada no rcclone Unix de Byron Rakitzis.

Warren Young
fonte
Se você gostaria de conhecer mais relações, por exemplo, com o UNOS "command", "bsh" e o recente Bourne Shell, envie-me uma nota. Como dica: o comando UNOS tinha um comando interno "do" que agia como um script de shell de uma linha com argumentos. Essa idéia foi transferida para o Bourne Shell como "dosh" e permite aliases parametrizáveis, algo que você não pode obter do ksh ou do bash.
schily
Pode-se notar que o próprio pdksh é baseado no shell Forsyth. Hoje praticamente esquecido, mas tem algum significado histórico na herança pdksh, mas também como foi o shell de algumas versões do minix e foi portado para msdos.
Stéphane Chazelas
25

"sh compatible" refere-se ao POSIXsh , o shell básico necessário para existir em todos os sistemas compatíveis. Um script compatível com sh deve funcionar em qualquer máquina compatível com POSIX.

A razão é necessário dizê-lo é que geralmente /bin/shé um link simbólico para /bin/bash, que deixou algumas Bashisms escorregar em scripts que se declaram usar shcom #!/bin/sh. Esses scripts não funcionam em sistemas que não usam bashcomo /bin/sh, incluindo alguns Unices comerciais para sempre, e Debian e derivados recentemente.

Em particular, tem havido uma tendência a usar dash, o Debian Almquish Shell, como o padrão shultimamente, porque é menor e deve ser mais rápido. Essa tendência destacou muitos desses bashismos que estavam em supostos shscripts. A descrição de algo como "compatível com sh" indica que se destina explicitamente a trabalhar com esses sistemas, mantendo-se inteiramente dentro da linguagem especificada no POSIX - todos os shells implementarão um superconjunto dessa funcionalidade, garantindo que funcione em qualquer lugar, mas suas extensões não são compatível um com o outro.

Os shells diferentes têm seu próprio histórico de desenvolvimento e divergem em diferentes direções ao longo do tempo, à medida que adicionam funções para ajudar o uso interativo de seus usuários ou extensões de script como matrizes associativas. Um script "incompatível com sh" usaria alguns desses recursos de extensão não padrão, como os [[condicionais de Bash .

Os recursos não-POSIX em bashe tcshe zshtodos os outros shells atuais são úteis , e há muitas ocasiões em que você pode querer ou precisar deles. Eles simplesmente não devem ser usados ​​em um script que se declara trabalhar /bin/sh, porque você não pode confiar nesses recursos na shimplementação básica no sistema em que está executando.

Um script que precisa usar, por exemplo, matrizes associativas, deve garantir que seja executado com bashe não sh:

#!/bin/bash
declare -A array

Isso funcionará em qualquer lugar bash. Os scripts que não precisam da funcionalidade estendida e devem ser portáveis ​​devem declarar que usam she mantêm a linguagem de comando do shell base.

Michael Homer
fonte