¿Cuándo es #!/bin/bash
más apropiado que #!/bin/sh
en un script de shell?
linux
shell-script
Hendré
fuente
fuente
bash
funciones y sintaxis en lugar desh
funciones y sintaxis.vim
resaltarábash
-ismos si su script tiene el#!/bin/sh
shebang. Solo lo cambio abash
si las cosas se ponen lo suficientemente peludas como para comenzar a necesitar funciones bash.$(...)
Es particularmente desagradable. Además, algunos de ellos son sutiles [<(...)
ycmd >& file
no reciben ningún resaltado de error, por ejemplo, simplemente no tienen resaltado especial para lo que quieren decir, con o sing:is_bash
]Respuestas:
En breve:
Hay varios shells que implementan un superconjunto de la especificación POSIX sh . En diferentes sistemas,
/bin/sh
puede haber un enlace a ash, bash, dash, ksh, zsh, & c. (Sin embargo, siempre será compatible con sh, nunca csh o fish).Siempre y cuando se limite a las
sh
características solamente, puede (y probablemente incluso debería) usar#!/bin/sh
y el script debería funcionar bien, sin importar de qué shell se trate.Si comienza a usar características específicas de bash (por ejemplo, matrices), debe solicitar específicamente bash, porque, incluso si
/bin/sh
ya invoca bash en su sistema, puede que no esté en el sistema de todos los demás , y su script no se ejecutará allí. (Lo mismo, por supuesto, se aplica a zsh y ksh). Puede usar shellcheck para identificar bashisms.Incluso si el script es solo para uso personal, puede notar que algunos sistemas operativos cambian
/bin/sh
durante las actualizaciones, por ejemplo, en Debian solía ser bash, pero luego se reemplazó con un guión muy mínimo. Guiones que usaban bashismos pero que de#!/bin/sh
repente se habían roto.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 laenv
herramienta en sí tampoco está estrictamente garantizada,/usr/bin/env
aún funciona en más sistemas que/bin/bash
).fuente
/bin/sh
entonces, intentará imitarsh
características (ver página de manual ), no estoy seguro de que las características específicas de bash estén disponibles en este modo.env
tool es una herramienta posix , debería encontrarse en la mayoría de las distribuciones, pero no estoy seguro, ya que algunos pueden no respetar posix./bin
: " Las aplicaciones deben tener en cuenta que la RUTA estándar al shell no se puede suponer que sea / bin / sh o / usr / bin / sh, y se debe determinar mediante la interrogación de la RUTA devuelta por getconf RUTA, asegurando que la ruta devuelta sea una ruta absoluta y no un shell incorporado ". También vea esta pregunta y, específicamente, esta respuesta .#!
funcionen los scripts?echo foo ^ cat
emitefoo ^ cat
en POSIX sh, y emite solofoo
en Bourne (como^
es un carácter de tubería allí).Use el shebang correspondiente al shell que realmente utilizó 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 las matrices ya que no se ha utilizado (o cualquierbash
característica que está consciente de), que está seguro de escoger cualquier cáscara te gusta. Hay muchas diferencias sutiles entre los shells (echo
funciones, bucles, lo que sea) que no se pueden descubrir sin una prueba adecuada.Considere esto: si se va
#!/bin/bash
y sus usuarios no lo tienen, verán un mensaje de error claro, algo así comoLa 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 lo prueba en un sistema donde/bin/sh
hay un enlace simbólico/bin/bash
, sus usuarios que no lo tenganbash
estarán en problemas. Lo más probable es que vean un mensaje de error críptico como:Esto puede tomar horas para solucionarlo, y no habrá idea sobre qué shell deberían haber utilizado.
No hay muchas razones por las que quieras usar un shell diferente en el shebang. Una razón es cuando el caparazón que ha utilizado no está muy extendido. Otra es ganar rendimiento con el
sh
cual es significativamente más rápido en algunos sistemas, Y su script será un cuello de botella de rendimiento. En ese caso, pruebe su script a fondo con el shell de destino, luego cambie el shebang.fuente
Solo deberías usarlo alguna vez
#! /bin/sh
.No debe usar extensiones bash (o zsh, o fish, o ...) en un script de shell, nunca.
Solo debe escribir scripts de shell que funcionen con cualquier implementación del lenguaje de shell (incluidos todos los programas de "utilidad" que acompañan al propio shell). En estos días, probablemente pueda tomar POSIX.1-2001 ( no -2008) como autoridad para lo que el shell y las utilidades son capaces de hacer, pero tenga en cuenta que algún día puede ser llamado para portar su script a un sistema heredado (por ejemplo, Solaris o AIX) cuyo shell y utilidades fueron congelados alrededor de 1992
¿Qué, en serio?
Sí, en serio.
Aquí está la cosa: Shell es un lenguaje de programación terrible . Lo único que tiene es que
/bin/sh
es el único intérprete de guiones que se garantiza que todas las instalaciones de Unix tengan.Aquí está la otra cosa:
/usr/bin/perl
es más probable que alguna iteración del intérprete principal de Perl 5 ( ) esté disponible en una instalación de Unix seleccionada al azar de lo que(/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash
está. Otros buenos lenguajes de scripting (Python, Ruby, node.js, etc. - Incluso incluiré PHP y Tcl en esa categoría al comparar con shell) también están 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 sea terrible.
Ahora, simples scripts de shell, del tipo que solo 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 matrices o funciones, ni
[[
siquiera. Y solo debe escribir scripts de shell complicados cuando no tiene otra opción. Las secuencias de comandos de Autoconf, por ejemplo, siguen siendo correctamente secuencias de comandos de shell. Pero esos scripts tienen que ejecutarse en cada encarnación/bin/sh
que sea 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 viejos Unix patentados en estos días, pero probablemente debería preocuparse por los BSD de código abierto actuales, algunos de los cuales no se instalanbash
de forma predeterminada, y entornos integrados que le brindan solo un shell y un mínimobusybox
.En conclusión, en el momento en que te encuentras queriendo una característica que no está disponible en el lenguaje shell portátil, eso es una señal de que el script se ha vuelto demasiado complicado para seguir siendo un script shell. Reescríbalo en un mejor idioma.
fuente
sh
. Eso, sin embargo, está muy lejos de afirmar que nunca debes usar otros proyectiles. Hay miles (probablemente muchos más) scripts escritos todos los días y la gran mayoría de ellos solo se ejecutarán en una sola máquina. Su consejo tiene sentido en el código de producción, pero no para los trabajos diarios de "sysdaminy" para los que se escriben la mayoría de los scripts. Si sé que mi script solo será utilizado por mí y en una máquina Linux, bash está bien.En general, si el tiempo es más importante que la funcionalidad, usará el shell más rápido. sh a menudo tiene el alias de guión y tiende a usarse para tareas cron de root u operaciones por lotes donde cada (nano) segundo cuenta.
fuente
Para ser aún más breve, use
sh
si la portabilidad en la mayoría de los sistemas es lo más importante ybash
si desea usar algunas de sus características específicas, como los arreglos, si la versión de bash lo admite.fuente
El camino más seguro. cuando está codificado, sería / usr / bin /
shellOfChoice
pero una nueva convención que trato de usar siempre ahora, ya que las 'ubicaciones predeterminadas' a través de un cambio PATH pueden cambiar es:#! / usr / bin / env sh o
#! / usr / bin / env bash
o, por ejemplo, scripts perl
#! / usr / bin / env perl -w
Por supuesto, cuando tiene una razón para que un script NUNCA tome una nueva RUTA automáticamente, continúe teniendo un código rígido, y luego / usr / bin / something debería ser la ruta más probable para usar.
fuente