En resumen:
-
Hay varios shells que implementan un superconjunto de la especificación POSIX sh. En diferentes sistemas,
/bin/sh
podría ser un enlace a ash, bash, dash, ksh, zsh, &c. (Sin embargo, siempre será compatible con sh, nunca csh o fish). -
Siempre y cuando te ciñas a
sh
solo funciones, puede (y probablemente incluso debería) usar#!/bin/sh
y el script debería funcionar bien, sin importar qué shell sea. -
Si comienza a usar funciones específicas de bash (por ejemplo, matrices), debe solicitar bash específicamente, porque, incluso si
/bin/sh
ya invoca bash en su sistema, puede que no esté en todos los demás sistema, y su secuencia de comandos no se ejecutará allí. (Por supuesto, lo mismo se aplica a zsh y ksh). Puede usar shellcheck para identificar bashisms. -
Incluso si la secuencia de comandos es solo para uso personal, es posible que observe que algunos sistemas operativos cambian
/bin/sh
durante las actualizaciones, p. en Debian solía ser bash, pero luego fue reemplazado por un guión mínimo. Scripts que usaban bashisms pero tenían#!/bin/sh
se rompió de repente.
Sin embargo:
-
Incluso
#!/bin/bash
no es muy correcto. En diferentes sistemas, bash podría vivir en/usr/bin
o/usr/pkg/bin
o/usr/local/bin
. -
Una opción más confiable es
#!/usr/bin/env bash
, que usa $PATH. (Aunque elenv
la herramienta en sí tampoco está estrictamente garantizada,/usr/bin/env
todavía funciona en más sistemas que/bin/bash
hace.)
Use el shebang correspondiente al shell que realmente usó para desarrollar y depurar su script. Es decir. si su shell de inicio de sesión es bash
, y ejecuta su script como ejecutable en su terminal, use #!/bin/bash
. No asuma que como no ha usado arreglos (o lo que sea bash
característica que conoce), puede elegir el caparazón que desee. Hay muchas diferencias sutiles entre las conchas (echo
, funciones, bucles, lo que sea) que no se pueden descubrir sin las pruebas adecuadas.
Considera esto:si dejas #!/bin/bash
y sus usuarios no lo tienen, verán un claro mensaje de error, algo así como
Error: /bin/bash not found
La mayoría de los usuarios pueden arreglar esto en menos de un minuto instalando el paquete apropiado. Por otro lado, si reemplaza el shebang por #!/bin/sh
y pruébelo en un sistema donde /bin/sh
es un enlace simbólico a /bin/bash
, sus usuarios que no tienen bash
estará en problemas. Lo más probable es que vean un mensaje de error críptico como:
Error in script.sh line 123: error parsing token xyz
Esto puede tardar horas en solucionarse y no habrá ninguna pista sobre qué shell deberían haber usado.
No hay muchas razones por las que querrías usar un caparazón diferente en el shebang. Una razón es cuando el caparazón que ha utilizado no está muy extendido. Otra es ganar rendimiento con sh
que es significativamente más rápido en algunos sistemas, Y su secuencia de comandos será un cuello de botella en el rendimiento. En ese caso, pruebe su secuencia de comandos a fondo con el shell de destino, luego cambie el shebang.
Solo deberías usar #! /bin/sh
.
Nunca debe usar extensiones bash (o zsh, fish o ...) en un script de shell.
Solo debe escribir scripts de shell que funcionen con any implementación del lenguaje de shell (incluidos todos los programas de "utilidad" que acompañan al propio shell). En estos días puedes probablemente tomar POSIX.1-2001 (no -2008) como autorizado para lo que el shell y las utilidades son capaces de hacer, pero tenga en cuenta que algún día se le pedirá que transfiera su script a un sistema heredado (por ejemplo, Solaris o AIX) cuyo shell y utilidades se congelaron alrededor de 1992.
¡¿Qué, en serio?!
Sí, en serio.
Aquí está la cosa:Shell es un terrible lenguaje de programación. Lo único que tiene es que /bin/sh
es el único intérprete de guiones que todos La instalación de Unix está garantizada.
Aquí está la otra cosa:alguna iteración del intérprete principal de Perl 5 (/usr/bin/perl
) es más probable que esté disponible en una instalación de Unix seleccionada al azar que (/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash
es. Otros buenos lenguajes de secuencias de comandos (Python, Ruby, node.js, etc.; incluso incluiré PHP y Tcl en esa categoría al compararlos con shell) también están tan disponibles como bash y otros shells extendidos.
Por lo tanto, si tiene la opción de escribir un script bash, tiene la opción de usar un lenguaje de programación que no es terrible, en su lugar.
Ahora, sencillo scripts de shell, del tipo que simplemente ejecuta algunos programas en una secuencia desde un trabajo cron o algo así, no hay nada de malo en dejarlos como scripts de shell. Pero los scripts de shell simples no necesitan arreglos o funciones o [[
incluso. Y solo debes escribir complicado scripts de shell cuando no tiene otra opción. Los scripts de Autoconf, por ejemplo, son correctamente scripts de shell. Pero esos scripts tienen que ejecutarse en todos encarnación de /bin/sh
eso es relevante para el programa que se está configurando. y eso significa que no pueden usar ninguna extensión. Probablemente no tenga que preocuparse por los antiguos Unix propietarios en estos días, pero probablemente debería preocuparse por los BSD de código abierto actuales, algunos de los cuales no instalan bash
de forma predeterminada, y entornos integrados que le brindan solo un shell mínimo y busybox
.
En conclusión, el momento en que te encuentras queriendo una característica que no está disponible en el lenguaje de shell portátil, eso es una señal de que el script se ha vuelto demasiado complicado para seguir siendo un script de shell. En su lugar, reescríbalo en un idioma mejor.