Escribir scripts de shell que se ejecutarán en cualquier shell (¿usando varias líneas shebang?)

Escribir scripts de shell que se ejecutarán en cualquier shell (¿usando varias líneas shebang?)

Recién comencé a profundizar en las secuencias de comandos de Shell, y siempre simplemente colocaba mi secuencia de comandos en un archivo, lo marcaba chmod +xy luego lo hacía /path/to/script.shy dejaba que el intérprete predeterminado se saliera con la suya, lo cual supuse que era zsh porque eso es lo que Lo usé para mi caparazón. Aparentemente parece que es solo /bin/shde forma predeterminada, incluso si ejecuto el script desde un indicador de zsh, porque comencé a poner cosas específicas de zsh en mis scripts y falla a menos que ejecute zsh /path/to/script.sh.

Para ir al grano, aquí están mis preguntas:

  1. ¿Qué shell ejecuta scripts cuando no hay una línea shebang ( #!/path/to/shell) al principio? Supongo /bin/shpero no puedo confirmarlo.
  2. ¿Qué se consideran "mejores prácticas" en términos de escritura de scripts de shell que se ejecutarán en cualquier plataforma? (vale, esto es una especie de final abierto)
  3. ¿Es posible escribir un script que intente utilizar zsh y recurra a bash si zsh no está disponible? Intenté poner dos líneas shebang, como a continuación, pero simplemente falla bad interpreter: /bin/zsh: no such file or directorysi lo intento en una máquina sin zsh.

    #!/bin/zsh

    #!/bin/bash

Respuesta1

¿Qué shell ejecuta scripts cuando no hay una línea shebang (#!/path/to/shell) al principio? Supongo que /bin/sh pero no puedo confirmarlo.

El kernel se niega a ejecutar dichos scripts y devuelve ENOEXEC, por lo que el comportamiento exacto depende del programa en el que ejecute dicho script.de.

  • bash 4.2.39 – se usa a sí mismo
  • Busybox-ash 1.20.2 – se usa a sí mismo
  • guión 0.5.7 – ejecuta /bin/sh
  • fish 1.23.1 – se queja de ENOEXEC y luego culpa al archivo equivocado
  • AT&T ksh 93u+2012.08.01 – se utiliza solo
  • mksh R40f – ejecuta /bin/sh
  • pdksh 5.2.14 – ejecuta /bin/sh
  • sh-heirloom 050706 – se usa solo
  • tcsh 6.18.01 – ejecuta /bin/sh
  • zsh 5.0.0 – ejecuta /bin/sh
  • cmd.exe 5.1.2600: te mira raro.

Englibc, funciones execv()o execve()simplemente devolver ENOEXEC. Pero execvp()oculta este código de error e invoca automáticamente /bin/sh. (Esto está documentado enejecutivo (3p).)

¿Qué se consideran "mejores prácticas" en términos de escritura de scripts de shell que se ejecutarán en cualquier plataforma? (vale, esto es una especie de final abierto)

Cíñete shúnicamente a las funciones definidas por POSIX o simplemente completaintento(que está ampliamente disponible) y menciónelo en sus requisitos si lo distribuye.

(Ahora que lo pienso, Perl – o quizás Python – sería aún más portátil, sin mencionar que tendría una mejor sintaxis).

Siempreagregue la línea shebang. Si usa bash o zsh, utilícelo #!/usr/bin/env bashen lugar de codificar la ruta del shell. (Sin embargo, se garantiza que el shell POSIX estará en /bin/sh, así que omítalo enven ese caso).

(Desafortunadamente, incluso /bin/shno siempre es lo mismo. El GNUconfiguración automáticaEl programa tiene que lidiar conmuchas peculiaridades diferentes.)

¿Es posible escribir un script que intente utilizar zsh y recurra a bash si zsh no está disponible? Intenté poner dos líneas shebang, como a continuación, pero solo aparecen errores conMal intérprete: /bin/zsh: no existe tal archivo o directorioSi lo pruebo en una máquina sin zsh.

Sólo puede haber una línea shebang; todo lo que sigue al carácter de nueva línea ni siquiera es leído por el kernel y los shells lo tratan como un comentario.

Esposiblepara escribir un script que se ejecute como #!/bin/sh, verifique qué shell está disponible y se ejecute exec zsh "$0" "$@"o exec bash "$0" "$@"según el resultado. Sin embargo, la sintaxis utilizada por bash y zsh es tan diferente en varios lugares que recomendaríano recomiendo hacer estopor tu propia cordura.

Respuesta2

1) El shell actual en el que estás ejecutando (cualquiera que sea el shell)

2) Siga con el mismo tipo de shell (bash/dash/ash/csh/cualquiera que sea su estilo) y asegúrese de que sus "plataformas compatibles" instalen el shell que desea usar de forma predeterminada. Además, intente utilizar comandos comúnmente disponibles en los sistemas. Evite opciones específicas de la máquina.

3) En realidad, no existe una lógica de "si-entonces-si no" en el archivo interpreter directive. Debe especificar un shell que debería existir en todos los sistemas que desea admitir... es decir, #!/bin/basho especificar un genérico #!/bin/shsiempre que su script sea bastante genérico en todos los shells.

información relacionada