¿Por qué es #!/usr/bin / env bash superior a #!/ bin / bash?


He visto en varios lugares, incluyendo recomendaciones en este sitio ( ¿Cuál es el Bash shebang preferido?), utilizar #!/usr/bin/env bash en lugar de #!/bin/bash. Incluso he visto a un individuo emprendedor sugerir que usar #!/bin/bash era incorrecto y la funcionalidad de bash se perdería al hacerlo.

Dicho esto, uso bash en un entorno de prueba estrechamente controlado donde cada unidad en circulación es esencialmente un clon de una sola unidad maestra. Entiendo la argumento de portabilidad, aunque no es necesariamente aplicable en mi caso. ¿Hay alguna otra razón para preferir #!/usr/bin/env bashsobre las alternativas y, asumiendo que la portabilidad era una preocupación, hay alguna razón para usarlo podría romper la funcionalidad?

 117
Author: Community, 2014-02-07

4 answers

#!/usr/bin/env busca PATH para bash, y bash no siempre está en /bin, particularmente en sistemas que no son Linux. Por ejemplo, en mi sistema OpenBSD, está en /usr/local/bin, ya que fue instalado como un paquete opcional.

Si está absolutamente seguro de que bash está en /bin y siempre lo estará, no hay ningún daño en ponerlo directamente en su shebang, pero lo desaconsejaría porque los scripts y programas tienen vidas más allá de lo que inicialmente creemos que tendrán.

 127
Author: zigg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-06 20:12:26

La ubicación estándar de bash es /bin, y sospecho que eso es cierto en todos los sistemas. Sin embargo, ¿qué pasa si no te gusta esa versión de bash? Por ejemplo, quiero usar bash 4.2, pero el golpe en mi Mac está en 3.2.5.

Podría intentar reinstalar bash en /bin pero eso puede ser una mala idea. Si actualizo mi sistema operativo, se sobrescribirá.

Sin embargo, podría instalar bash en /usr/local/bin/bash, y configurar mi RUTA a:

PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

Ahora, si especifico bash, no obtengo el viejo cruddy en /bin/bash, pero el más nuevo y brillante en /usr/local/bin. ¡Bonito!

Excepto que mis scripts de shell tienen ese !# /bin/bash shebang. Por lo tanto, cuando corro mis scripts de shell, obtengo esa versión vieja y pésima de bash que ni siquiera tiene matrices asociativas.

Usando /usr/bin/env bash usaré la versión de bash que se encuentra en mi CAMINO. Si configuro mi RUTA, para que /usr/local/bin/bash se ejecute, ese es el bash que mis scripts usarán.

Es raro ver esto con bash, pero es mucho más común con Perl y Python:

  • Ciertas versiones de Unix/Linux que se centran en la estabilidad a veces están muy por detrás con la liberación de estos dos lenguajes de scripting. No hace mucho tiempo, RHEL's Perl estaba en 5.8.8 an ¡una versión de ocho años de Perl! Si alguien quería usar funciones más modernas, tenía que instalar su propia versión.
  • Programas como Perlbrew y Pythonbrew le permiten instalar múltiples versiones de estos lenguajes. Dependen de scripts que manipulan su CAMINO para obtener la versión que quieras. Codificar la ruta significa que no puedo ejecutar mi script bajo brew .
  • No fue hace mucho tiempo (vale, fue hace mucho tiempo) que Perl y Python no eran paquetes estándar incluidos en la mayoría de los sistemas Unix. Eso significaba que no sabías dónde estaban instalados estos dos programas. Fue bajo /bin? /usr/bin? /opt/bin? Quién sabe? Usar #! /usr/bin/env perl significaba que no tenía que saberlo.

Y Ahora Por Qué No Debes Usar #! /usr/bin/env bash

Cuando la ruta está codificada en el shebang, tengo que correr con ese intérprete. Por lo tanto, #! /bin/bash me obliga a usar la versión instalada por defecto de bash. Dado que las características de bash son muy estables (intente ejecutar un 2.versión x de un script de Python bajo Python 3.x) es muy poco probable que mi script BASH en particular no funcione, y dado que mi script bash es probablemente utilizado por este sistema y otros sistemas, el uso de una versión no estándar de bash puede tener efectos no deseados. Es muy probable que quiera asegurarse de que la versión estándar estable de bash se usa con mi script de shell. Por lo tanto, probablemente quiero codificar la ruta en mi shebang.

 24
Author: David W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-16 21:35:46

Para invocar bash es un poco exagerado. A menos que tenga varios binarios bash como el suyo en ~/bin, pero eso también significa que su código depende de que PATH PATH tenga las cosas correctas en él.

Sin embargo, es útil para cosas como python. Hay scripts y entornos wrapper que conducen a usar binarios alternativos python.

Pero nada se pierde al usar la ruta exacta al binario, siempre y cuando esté seguro de que es el binario que realmente desea.

 10
Author: Sean Perry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-06 20:12:17

Hay muchos sistemas que no tienen Bash en /bin, FreeBSD y OpenBSD solo por nombrar algunos. Si su script está destinado a ser portable a muchas unidades diferentes, es posible que desee usar #!/usr/bin/env bash en lugar de #!/bin/bash.

Tenga en cuenta que esto no es cierto para sh; para scripts compatibles con Bourne uso exclusivamente #!/bin/sh, ya que creo que casi todos los Unix existentes tienen sh en /bin.

 7
Author: James Ko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-28 03:52:07