¿Cuál es el Bash shebang preferido?

1132

¿Hay algún Bashshebang objetivamente mejor que los demás para la mayoría de los usos?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -
  • etc.

Recuerdo vagamente hace mucho tiempo que escuché que agregar un guión al final evita que alguien pase un comando a su script, pero no puedo encontrar ningún detalle al respecto.

Curtosis
fuente
44
Y está /usr/local/bin/bashen OpenBSD.
jww

Respuestas:

1536

Debe usar #!/usr/bin/env bashpara la portabilidad : diferentes * nixes colocados bashen diferentes lugares, y el uso /usr/bin/enves una solución alternativa para ejecutar el primero bashencontrado en el PATH. Y shno lo esbash .

l0b0
fuente
99
Gracias. También parece que agregar - al final de $! / Usr / bin / env bash - no hará nada ya que solo * nix permite el argumento en shebang, y 'bash' lo usa. Aparentemente, eso solo es útil para evitar que se pasen argumentos maliciosos al script en la línea de comandos si el shebang del script es uno de los otros sin argumentos ( /bin/sh, etc.).
Kurtosis
13
@Ray bashno vive en /bintodos los sistemas.
ptierno 01 de
12
Lo mismo para mí, lo acabo de agregar a un alias: alias shebang='echo "#!/usr/bin/env bash"'ahora solo tengo que abrir el terminal y escribir shebang en lugar de ir aquí.
Oylex
19
Esta respuesta es engañosa. POSIX no dice que envesté en /usr/bin/env. De hecho, podría estar en /bin/envcualquier lugar, siempre que esté en el camino. Podría estar en /dummy/envsi /dummyestá adentro PATH. Shebang no está definido en POSIX, por lo que podría hacer que se #!stop toasterinicie la máquina de café USB y cumplir con POSIX. Por #!/usr/bin/env bashlo tanto, no es particularmente mejor que #!/bin/bash, podría ser menos portátil dependiendo.
darkfeline
19
La portabilidad de @darkfeline no es absoluta: es matemáticamente imposible crear un script que haga lo mismo en todas las plataformas. A partir de 2012 hasta 2018 /usr/bin/envexiste en más máquinas que cualquiera de /bin/bashxor /usr/bin/bash, por lo que un script que comienza con esta línea hará lo esperado en tantas máquinas como sea posible.
l0b0
80

/bin/shgeneralmente es un enlace al shell predeterminado del sistema, que a menudo está activado bash, por ejemplo, los sistemas Debian son más livianos dash. De cualquier manera, el shell Bourne original es sh, por lo que si su script usa algunas bashcaracterísticas específicas ( [[ ]]pruebas de segunda generación, "Bourne Again sh") ( pruebas, matrices, varias cosas azucaradas, etc.), entonces debería ser más específico y usar el posterior . De esta manera, en sistemas donde bash no está instalado, su script no se ejecutará. Entiendo que puede haber una trilogía emocionante de películas sobre esta evolución ... pero eso podría ser un rumor.

También tenga en cuenta que cuando se evoca como sh, bashen cierta medida se comporta como estándar POSIX sh (ver también los documentos de GNU sobre esto).

delicadaLaticeworkFever
fuente
2
El Public Domain Korn Shell (pdksh) está predeterminado en OpenBSD.
jww
La mayoría de los sistemas no se vincularán /bin/sha ninguna parte /usrya que eso dificultaría la ejecución de los scripts de inicio antes de que /usrse monte.
aij
@aij No sé por qué puse "muchos o la mayoría" allí: soy un usuario de fedora, donde /biny /sbindurante años solo he sido enlaces simbólicos por defecto, hacia /usr/biny /usr/sbin, por lo que en ese contexto /bin/shhay un enlace bashy directorio es /usr/bin. Pero corregiré lo anterior.
delicateLatticeworkFever
44

Recomiendo usar:

#!/bin/bash

No es 100% portátil (algunos sistemas se ubican bashen una ubicación distinta a /bin), pero el hecho de que muchos scripts existentes usan #!/bin/bashpresiones de varios sistemas operativos para hacer /bin/bashal menos un enlace simbólico a la ubicación principal.

La alternativa de:

#!/usr/bin/env bash

ha sido sugerido, pero no hay garantía de que el envcomando esté en /usr/bin(y he usado sistemas donde no está). Además, este formulario usará la primera instancia de bashen los usuarios actuales $PATH, que podría no ser una versión adecuada del shell bash.

(Pero /usr/bin/envdebería funcionar en cualquier sistema razonablemente moderno, ya sea porque envestá /usr/bino porque el sistema hace algo para que funcione. El sistema al que me referí anteriormente era SunOS 4, que probablemente no he usado en unos 25 años).

Si necesita ejecutar un script en un sistema que no lo tiene /bin/bash, puede modificar el script para que apunte a la ubicación correcta (eso es ciertamente inconveniente).

He discutido las compensaciones con mayor profundidad en mi respuesta a esta pregunta .

Una actualización algo oscura: un sistema que uso, Termux , una capa de escritorio similar a Linux que se ejecuta en Android, no tiene /bin/bash( bashes /data/data/com.termux/files/usr/bin/bash), pero tiene un manejo especial para soportar #!/bin/bash.

Keith Thompson
fuente
3
2 años después y este sigue siendo el mejor consejo aquí. Si la solución simple no funciona, entonces debes cuestionar tus decisiones anteriores. La respuesta aceptada y más votada no es incorrecta, simplemente no es correcta :)
Ingeniero de software
27

Usar una línea shebang para invocar al intérprete apropiado no es solo para BASH. Puede usar el shebang para cualquier lenguaje interpretado en su sistema, como Perl, Python, PHP (CLI) y muchos otros. Por cierto, el shebang

#!/bin/sh -

(también puede ser dos guiones, es decir --) finaliza las opciones de bash, todo lo que sea posterior se tratará como nombres de archivo y argumentos.

El uso del envcomando hace que su script sea portátil y le permite configurar entornos personalizados para su script, por lo tanto, los scripts portátiles deben usar

#!/usr/bin/env bash

O para cualquier idioma como Perl

#!/usr/bin/env perl

Asegúrese de mirar las manpáginas para bash:

man bash

y env:

man env

Nota: en Debian y los sistemas basados ​​en Debian, como Ubuntu, shestán vinculados a dashnot bash. Como todos los scripts del sistema usan sh. Esto permite que bash crezca y el sistema se mantenga estable, según Debian.

Además, para mantener la invocación * nix como nunca uso extensiones de archivo en scripts invocados shebang, ya que no puede omitir la extensión de invocación en ejecutables como puede hacerlo en Windows. El comando de archivo puede identificarlo como un script.

Jamie R Robillard Sr.
fuente
4

Realmente depende de cómo escribas tus scripts de bash. Si su /bin/shenlace simbólico a bash, cuando se invoca bash como sh, algunas características no están disponibles .

Si desea funciones específicas de bash que no sean POSIX, use #!/bin/bash

Glenn Jackman
fuente
3
Bash no está instalado en OpenBSD. Si lo instala a través de pkg_add, entonces está ubicado en /usr/local/bin, que puede no estar en ruta.
jww
¿ POSIXQué tal una característica?
Nikolan Asad