Si les scripts shell commencent par #!/bin/bash, ils seront toujours exécutés avec bashfrom /bin. S'ils commencent cependant par #!/usr/bin/env bash, ils chercheront bashdans $PATHpuis commenceront par le premier qu'ils peuvent trouver.
Pourquoi cela serait-il utile? Supposons que vous vouliez exécuter des bashscripts, qui nécessitent bash 4.x ou plus récent, mais votre système n'a que bash3.x installé et actuellement votre distribution n'offre pas une version plus récente ou vous n'êtes pas administrateur et ne pouvez pas changer ce qui est installé sur ce système .
Bien sûr, vous pouvez télécharger le code source bash et créer votre propre bash à partir de zéro, en le plaçant ~/binpar exemple. Et vous pouvez également modifier votre $PATHvariable dans votre .bash_profilefichier pour l'inclure ~/bincomme première entrée ( PATH=$HOME/bin:$PATHcar ~elle ne sera pas développée dans $PATH). Si vous appelez maintenant bash, le shell va d'abord le chercher $PATHdans l'ordre, il commence donc par ~/binoù il trouvera votre fichier bash. La même chose se produit si les scripts recherchent l' bashutilisation #!/usr/bin/env bash, de sorte que ces scripts fonctionneraient désormais sur votre système à l'aide de votre bashgénération personnalisée .
Un inconvénient est que cela peut conduire à un comportement inattendu, par exemple le même script sur la même machine peut s'exécuter avec différents interprètes pour différents environnements ou utilisateurs avec des chemins de recherche différents, provoquant toutes sortes de maux de tête.
Le plus gros inconvénient envest que certains systèmes n'autorisent qu'un seul argument, vous ne pouvez donc pas le faire #!/usr/bin/env <interpreter> <arg>, car les systèmes le verront <interpreter> <arg>comme un seul argument (ils le traiteront comme si l'expression était citée) et envrechercheront donc un interprète nommé <interpreter> <arg>. Notez que ce n'est pas un problème de la envcommande elle-même, qui a toujours permis de passer plusieurs paramètres mais avec l'analyseur shebang du système qui analyse cette ligne avant même d'appeler env. Pendant ce temps, cela a été corrigé sur la plupart des systèmes, mais si votre script veut être ultra portable, vous ne pouvez pas compter que cela a été corrigé sur le système que vous exécuterez.
Il peut même avoir des implications sur la sécurité, par exemple s'il sudon'a pas été configuré pour nettoyer l'environnement ou a $PATHété exclu du nettoyage. Permettez-moi de le démontrer:
/binEst généralement un endroit bien protégé, seul rootpeut y changer quoi que ce soit. Cependant, votre répertoire personnel n’est pas un programme que vous exécutez peut y apporter des modifications. Cela signifie qu'un code malveillant pourrait placer un faux bashdans un répertoire caché, modifiez votre .bash_profilepour inclure ce répertoire dans votre $PATH, afin que tous les scripts utilisant #!/usr/bin/env bashfinissent par fonctionner avec ce faux bash. Si ça sudocontinue $PATH, vous avez de gros ennuis.
Par exemple, considérez qu'un outil crée un fichier ~/.evil/bashavec le contenu suivant:
#!/bin/bash
if [ $EUID -eq 0 ]; then
echo "All your base are belong to us..."
# We are root - do whatever you want to do
fi
/bin/bash "$@"
Faisons un script simple sample.sh:
#!/usr/bin/env bash
echo "Hello World"
Preuve de concept (sur un système où se sudoconserve $PATH):
$ ./sample.sh
Hello World
$ sudo ./sample.sh
Hello World
$ export PATH="$HOME/.evil:$PATH"
$ ./sample.sh
Hello World
$ sudo ./sample.sh
All your base are belong to us...
Hello World
Habituellement, les shells classiques doivent tous être situés dans /binet si vous ne voulez pas les placer là pour une raison quelconque, ce n'est vraiment pas un problème de placer un lien symbolique /binqui pointe vers leur emplacement réel (ou peut /bin- être lui - même est un lien symbolique), donc J'irais toujours avec #!/bin/shet #!/bin/bash. Il y a trop de choses qui se briseraient si elles ne fonctionnaient plus. Ce n'est pas que POSIX aurait besoin de ces positions (POSIX ne standardise pas les noms de chemin et donc il ne standardise même pas du tout la fonctionnalité shebang) mais ils sont si courants que même si un système ne proposait pas de /bin/sh, il comprendrait probablement #!/bin/shet savoir quoi en faire et que ce ne soit que pour la compatibilité avec le code existant.
Mais pour les interprètes optionnels plus modernes et non standard comme Perl, PHP, Python ou Ruby, il n'est pas vraiment spécifié où ils devraient être situés. Ils peuvent être en , /usr/binmais ils peuvent aussi bien être /usr/local/binou dans une branche de la hiérarchie complètement différente ( /opt/..., /Applications/..., etc.). C'est pourquoi ceux-ci utilisent souvent la #!/usr/bin/env xxxsyntaxe shebang.