GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cuándo debo usar #!/bin/bash y cuándo #!/bin/sh?

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 el env 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.


Linux
  1. ¿Cómo maneja Linux múltiples separadores de rutas consecutivas (/home////username///file)?

  2. Bash =~ Regex y Https://regex101.com/?

  3. Linux – ¿Fusionar /usr/bin y /usr/sbin en /bin (gnu/linux)?

  4. ¿Qué es diferente entre /bin/false y /sbin/nologin como shell del usuario nologin?

  5. Instalar binarios en /bin, /sbin, /usr/bin y /usr/sbin, interacciones con --prefix y DESTDIR

¿Por qué /bin/sh apunta a /bin/dash y no a /bin/bash?

cmake --version apunta a /usr/bin/cmake mientras que cmake apunta a /usr/local/bin

¿Cuándo debo usar /dev/shm/ y cuándo debo usar /tmp/?

Diferencia entre /bin y /usr/bin

¿Deberían vivir los sitios web en /var/ o /usr/ según el uso recomendado?

#!/bin/sh vs #!/bin/bash para máxima portabilidad