web-dev-qa-db-fra.com

Pourquoi #! / Usr / bin / env bash est-il supérieur à #! / Bin / bash?

J'ai vu dans un certain nombre d'endroits, y compris des recommandations sur ce site ( Quel est le bash shebang préféré? ), pour utiliser #!/usr/bin/env bash de préférence à #!/bin/bash. J'ai même vu un individu entreprenant suggère d'utiliser #!/bin/bash était faux et la fonctionnalité de bash serait perdue en faisant alors.

Cela dit, j’utilise bash dans un environnement de test très contrôlé, où chaque disque en circulation est essentiellement un clone d’un disque maître unique. Je comprends l'argument de la transférabilité, même s'il n'est pas nécessairement applicable dans mon cas. Existe-t-il une autre raison de préférer #!/usr/bin/env bash par rapport aux solutions de remplacement et, en supposant que la portabilité pose problème, existe-t-il une raison pour laquelle l'utilisation pourrait en altérer le fonctionnement?

170
spugm1r3

#!/usr/bin/env recherche PATH pour bash et bash n'est pas toujours dans /bin, en particulier sur les systèmes non Linux. Par exemple, sur mon système OpenBSD, il se trouve dans /usr/local/bin, car il a été installé en tant que package facultatif.

Si vous êtes absolument sûr que bash est dans /bin et qu'il le restera toujours, rien ne vous empêche de le mettre directement dans votre Shebang - mais je vous le déconseille crois d'abord qu'ils auront.

192
zigg

L'emplacement standard de bash est /bin et je suppose que c'est le cas sur tous les systèmes. Cependant, si vous n'aimez pas cette version de bash? Par exemple, je veux utiliser bash 4.2, mais le bash sur mon Mac est à 3.2.5.

Je pourrais essayer de réinstaller bash dans /bin mais cela peut être une mauvaise idée. Si je mets à jour mon système d'exploitation, il sera écrasé.

Cependant, je pourrais installer bash dans /usr/local/bin/bash et configurer mon CHEMIN pour:

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

Maintenant, si je spécifie bash, je ne reçois pas le vieux cruddy à /bin/bash, mais le plus récent et le plus brillant à /usr/local/bin. Agréable!

Sauf que mes scripts Shell ont ce !# /bin/bash Shebang. Ainsi, lorsque j’exécute mes scripts Shell, j’ai cette ancienne et moche version de bash qui n’a même pas de tableaux associatifs.

Utiliser /usr/bin/env bash utilisera la version de bash trouvée dans my PATH. Si je configure mon PATH, de sorte que /usr/local/bin/bash soit exécuté, c'est la bash que mes scripts vont utiliser.

C'est rare de voir cela avec bash, mais c'est beaucoup plus courant avec Perl et Python:

  • Certaines versions Unix/Linux qui se concentrent sur stabilité sont parfois bien en retard avec la publication de ces deux langages de script. Il n'y a pas si longtemps, Perl de RHEL était à 5.8.8 - une version de Perl vieille de huit ans! Si quelqu'un voulait utiliser des fonctionnalités plus modernes, vous deviez installer votre propre version.
  • Des programmes tels que Perlbrew et Pythonbrew vous permettent d’installer plusieurs versions de ces langues. Ils dépendent des scripts qui manipulent votre PATH pour obtenir la version souhaitée. Un codage dur du chemin signifie que je ne peux pas exécuter mon script sous brew.
  • Il n'y a pas si longtemps (d'accord, il y a bien longtemps), Perl et Python n'étaient pas des paquetages standard inclus dans la plupart des systèmes Unix. Cela signifiait que vous ne saviez pas où ces deux programmes étaient installés. Était-ce sous /bin? /usr/bin? /opt/bin? Qui sait? Utiliser #! /usr/bin/env Perl signifiait que je n'avais pas besoin de savoir.

Et maintenant, pourquoi ne pas utiliser #! /usr/bin/env bash

Lorsque le chemin est codé en dur dans le Shebang, je dois courir avec cet interprète. Ainsi, #! /bin/bash me force à utiliser la version installée par défaut de bash. Comme les fonctionnalités de bash sont très stables (essayez d’exécuter une version 2.x d’un script Python sous Python 3.x), il est très improbable que mon script BASH ne fonctionne pas. mon script bash est probablement utilisé par ce système et d'autres systèmes, l'utilisation d'une version non standard de bash pouvant avoir des effets indésirables. Il est très probable que je veuille m'assurer que la version standard stable de bash est utilisée avec mon script Shell. Ainsi, je veux probablement coder dur le chemin dans mon Shebang.

30
David W.

Pour invoquer bash c'est un peu exagéré. Sauf si vous avez plusieurs fichiers binaires bash comme le vôtre dans ~/bin, cela signifie également que votre code dépend du fait que $ PATH contienne les éléments appropriés.

C'est pratique pour des choses comme python cependant. Il existe des scripts de wrapper et des environnements qui conduisent à l'utilisation de binaires python alternatifs.

Mais rien n’est perdu en utilisant le chemin exact du binaire tant que vous êtes sûr que c’est le binaire que vous voulez vraiment.

11
Sean Perry

Il y a beaucoup de systèmes qui n'ont pas Bash dans /bin, FreeBSD et OpenBSD pour n'en nommer que quelques-uns. Si votre script doit être portable sur de nombreux Unices différents, vous pouvez utiliser #!/usr/bin/env bash au lieu de #!/bin/bash.

Notez que cela n'est pas vrai pour sh; pour les scripts compatibles Bourne, j'utilise exclusivement #!/bin/sh, car je pense que tous les Unix existants ont sh dans /bin.

10
James Ko
 #!/usr/bin/env bash

est certainement meilleur car il trouve le chemin exécutable bash à partir de votre variable d’environnement système.

Allez dans votre shell Linux et tapez

env

Il imprimera toutes vos variables d'environnement.

Allez dans votre script shell et tapez

echo $bash.

Il imprimera votre chemin bash (en fonction de la liste de variables d'environnement) que vous devriez utiliser pour construire votre chemin Shebang correct dans votre script.

0
kta