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érer d’utiliser #!/bin/bash était faux et la fonctionnalité bash serait perdue en le faisant.

Cela dit, j’utilise bash dans un environnement de test étroitement contrôlé où chaque disque en circulation est essentiellement un clone d’un seul disque maître. Je comprends l’argument de la portabilité, même s’il n’est pas nécessairement applicable dans mon cas. Y a-t-il une autre raison de préférer #!/usr/bin/env bash aux alternatives et, en supposant que la portabilité soit un problème, y a-t-il une raison pour laquelle cela pourrait casser la fonctionnalité?

#!/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 le sera toujours, il n’y a pas de mal à le mettre directement dans votre shebang, mais je le déconseillerai car les scripts et les programmes ont tous une vie supérieure à ce qu’ils pensent.

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

Je pourrais essayer de réinstaller bash in /bin mais c’est peut-être une mauvaise idée. Si je mets à jour mon système d’exploitation, il sera remplacé.

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

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

Maintenant, si je spécifie bash , je n’obtiens pas l’ancien cruddy à /bin/bash , mais le plus récent à /usr/local/bin . Agréable!

Sauf que mes scripts shell ont cela !# /bin/bash shebang. Ainsi, lorsque je lance mes scripts shell, j’obtiens 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 mon PATH. Si je configure mon PATH pour que /usr/local/bin/bash soit exécuté, c’est la bash que mes scripts utiliseront.

C’est rare de voir ça avec bash, mais c’est beaucoup plus commun avec Perl et Python:

  • Certaines versions d’Unix / Linux axées sur la stabilité sont parfois loin derrière avec la sortie de ces deux langages de script. Il y a peu de temps, 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 langages. Ils dépendent des scripts qui manipulent votre PATH pour obtenir la version souhaitée. Le codage difficile du chemin signifie que je ne peux pas exécuter mon script sous l’ infusion .
  • Il n’y a pas si longtemps (d’accord, il y a longtemps), Perl et Python n’étaient pas des paquets standard inclus dans la plupart des systèmes Unix. Cela signifie que vous ne saviez pas où ces deux programmes étaient installés. Était-ce sous /bin ? /usr/bin ? /opt/bin ? Qui sait? En utilisant #! /usr/bin/env perl #! /usr/bin/env perl signifiait que je n’avais pas besoin de savoir.

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

Lorsque le chemin est codé en dur dans le shebang, je dois courir avec cet interprète. Ainsi, #! /bin/bash #! /bin/bash me force à utiliser la version installée par défaut de bash. Comme les fonctionnalités 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 peu probable que mon script BASH ne fonctionne pas et que mon script bash est probablement utilisé par ce système et d’autres systèmes , utiliser une version non standard de bash peut avoir des effets indésirables. Il est très probable que je veux 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.

Pour invoquer bash c’est un peu exagéré. À moins que vous ayez plusieurs binarys bash comme le vôtre dans ~ / bin mais que cela signifie aussi que votre code dépend de $ PATH.

C’est pratique pour des choses comme python si. Il existe des scripts et des environnements wrapper qui permettent d’utiliser des binarys python alternatifs.

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

Il y a beaucoup de systèmes qui n’ont pas Bash in /bin , FreeBSD et OpenBSD pour n’en nommer que quelques-uns. Si votre script est destiné à être portable sur plusieurs 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 qu’à peu près tous les Unix existants sh /bin .