Escrevendo scripts de shell que serão executados em qualquer shell (usando várias linhas shebang?)

Escrevendo scripts de shell que serão executados em qualquer shell (usando várias linhas shebang?)

Acabei de começar a me aprofundar nos scripts de shell e sempre joguei meu script em um arquivo, marquei-o chmod +xe pronto /path/to/script.sh, e deixei qualquer intérprete padrão agir com ele, o que presumi ser zsh porque é isso que Eu usei para minha concha. Aparentemente, parece que é apenas /bin/shpor padrão, mesmo se eu executar o script a partir de um prompt zsh, porque comecei a colocar coisas específicas do zsh em meus scripts e ele está falhando, a menos que eu execute o zsh /path/to/script.sh.

Para ir direto ao ponto, aqui estão minhas perguntas:

  1. Qual shell executa scripts quando não há linha Shebang ( #!/path/to/shell) no início? Presumo /bin/shmas não posso confirmar.
  2. O que é considerado "melhores práticas" em termos de escrita de scripts de shell que serão executados em qualquer plataforma? (ok, isso é meio aberto)
  3. É possível escrever um script que tente usar o zsh e volte ao bash se o zsh não estiver disponível? Eu tentei colocar duas linhas shebang, como abaixo, mas só dá erro bad interpreter: /bin/zsh: no such file or directoryse eu tentar em uma máquina sem zsh.

    #!/bin/zsh

    #!/bin/bash

Responder1

Qual shell executa scripts quando não há linha shebang (#!/path/to/shell) no início? Presumo /bin/sh mas não posso confirmar.

O kernel se recusa a executar tais scripts e retorna ENOEXEC, então o comportamento exato depende do programa em que você executa tal scriptde.

  • bash 4.2.39 – usa a si mesmo
  • busybox-ash 1.20.2 – usa a si mesmo
  • traço 0.5.7 – executa /bin/sh
  • fish 1.23.1 – reclama do ENOEXEC, depois culpa o arquivo errado
  • AT&T ksh 93u+2012.08.01 – usa a si mesmo
  • mksh R40f – executa /bin/sh
  • pdksh 5.2.14 – executa /bin/sh
  • sh-heirloom 050706 – usa a si mesmo
  • tcsh 6.18.01 – executa /bin/sh
  • zsh 5.0.0 – executa /bin/sh
  • cmd.exe 5.1.2600 – olha para você de forma engraçada.

Emglibc, funções execv()ou execve()apenas retornar ENOEXEC. Mas execvp()oculta esse código de erro e invoca automaticamente /bin/sh. (Isso está documentado emexecutivo(3p).)

O que é considerado "melhores práticas" em termos de escrita de scripts de shell que serão executados em qualquer plataforma? (ok, isso é meio aberto)

Atenha-se shapenas aos recursos definidos pelo POSIX ou simplesmente vá completofesta(que está amplamente disponível) e mencione-o em seus requisitos se for distribuí-lo.

(Agora que penso nisso, Perl – ou talvez Python – seria ainda mais portátil, sem mencionar que teria uma sintaxe melhor.)

Sempreadicione a linha shebang. Se estiver usando bash ou zsh, use #!/usr/bin/env bashem vez de codificar o caminho do shell. (No entanto, é garantido que o shell POSIX esteja em /bin/sh, portanto pule envnesse caso.)

(Infelizmente, /bin/shnem sempre é o mesmo. O GNUautoconfprograma tem que lidar commuitas peculiaridades diferentes.)

É possível escrever um script que tente usar o zsh e volte ao bash se o zsh não estiver disponível? Eu tentei colocar duas linhas Shebang, como abaixo, mas apenas erros comintérprete ruim: /bin/zsh: arquivo ou diretório inexistentefora se eu tentar em uma máquina sem zsh.

Só pode haver uma linha shebang; tudo depois do caractere de nova linha nem é lido pelo kernel e tratado como um comentário pelos shells.

Isso épossívelpara escrever um script que seja executado como #!/bin/sh, verifique qual shell está disponível e execute exec zsh "$0" "$@"ou exec bash "$0" "$@"dependendo do resultado. No entanto, a sintaxe usada pelo bash e pelo zsh é tão diferente em vários lugares que eu gostarianão recomendo fazer issopara sua própria sanidade.

Responder2

1) O shell atual em que você está executando. (qualquer que seja o shell)

2) Fique com o mesmo tipo de shell (bash/dash/ash/csh/qualquer que seja seu tipo) e certifique-se de que suas "plataformas suportadas" instalem o shell que você deseja usar por padrão. Além disso, tente usar comandos comumente disponíveis nos sistemas. Evite opções específicas da máquina.

3) Não existe realmente uma lógica "se-então-senão" para o arquivo interpreter directive. Você deve especificar um shell que deve existir em todos os sistemas que você deseja suportar... ou seja, #!/bin/bashou especificar um genérico, #!/bin/shdesde que seu script seja bastante genérico em todos os shells.

informação relacionada