Si les scripts shell commencent par #!/bin/bash
ils fonctionneront toujours avec bash
de /bin
. Si toutefois ils commencent par #!/usr/bin/env bash
ils chercheront bash
sur $PATH
et commencer avec le premier qu'ils peuvent trouver.
Pourquoi cela serait-il utile ? Supposons que vous vouliez exécuter bash
qui requièrent bash 4.x ou plus récent, alors que votre système n'a que bash
3.x installé et actuellement votre distribution ne propose pas de version plus récente ou vous n'êtes pas administrateur et ne pouvez pas changer ce qui est installé sur ce système.
Bien entendu, vous pouvez télécharger le code source de bash et construire votre propre bash à partir de zéro, en le plaçant dans le répertoire ~/bin
par exemple. Et vous pouvez également modifier votre $PATH
dans votre .bash_profile
pour inclure ~/bin
comme première entrée ( PATH=$HOME/bin:$PATH
como ~
ne se développera pas en $PATH
). Si vous appelez maintenant bash
le shell le cherchera d'abord dans $PATH
dans l'ordre, donc il commence par ~/bin
où il trouvera votre bash
. La même chose se produit si les scripts recherchent bash
en utilisant #!/usr/bin/env bash
Ainsi, ces scripts fonctionneraient maintenant sur votre système en utilisant votre code d'accès personnalisé. bash
construire.
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 différents chemins de recherche, causant toutes sortes de maux de tête.
Le plus gros inconvénient avec env
est que certains systèmes ne permettent qu'un seul argument, donc vous ne pouvez pas faire ceci #!/usr/bin/env <interpreter> <arg>
comme les systèmes le verront <interpreter> <arg>
comme un seul argument (ils le traiteront comme si l'expression était citée) et donc env
cherchera un interprète nommé <interpreter> <arg>
. Notez que ce n'est pas un problème de la env
elle-même, qui permet toujours le passage de plusieurs paramètres, mais avec l'analyseur Shebang du système qui analyse cette ligne avant même d'appeler la commande env
. Entre-temps, cela a été corrigé sur la plupart des systèmes mais si votre script veut être ultra portable, vous ne pouvez pas compter sur le fait que cela a été corrigé sur le système que vous allez exécuter.
Cela peut même avoir des conséquences sur la sécurité, par exemple si sudo
n'a pas été configuré pour un environnement propre ou $PATH
a été exclu du nettoyage. Permettez-moi d'en faire la démonstration :
Habituellement /bin
est un endroit bien protégé, seulement root
est capable d'y changer quoi que ce soit. Votre répertoire personnel ne l'est pas, cependant, tout programme que vous exécutez est capable d'y apporter des modifications. Cela signifie qu'un code malveillant pourrait placer un faux bash
dans un répertoire caché, modifiez votre .bash_profile
pour inclure ce répertoire dans votre $PATH
Ainsi, tous les scripts utilisant #!/usr/bin/env bash
finira par fonctionner avec ce faux bash
. Si sudo
garde $PATH
vous avez de gros problèmes.
Par exemple, considérons qu'un outil crée un fichier ~/.evil/bash
avec 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 simple script. sample.sh
:
#!/usr/bin/env bash
echo "Hello World"
Preuve de concept (sur un système où sudo
garde $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 le répertoire /bin
et si vous ne voulez pas les placer là pour une raison quelconque, il n'y a pas de problème à placer un lien symbolique dans le répertoire /bin
qui pointe vers leurs emplacements réels (ou peut-être /bin
est lui-même un lien symbolique), j'utiliserais donc toujours #!/bin/sh
y #!/bin/bash
. Il y a trop de choses qui se briseraient si ces positions ne fonctionnaient plus. Ce n'est pas que POSIX exige ces positions (POSIX ne standardise pas les noms de chemin et donc ne standardise pas du tout la fonctionnalité shebang) mais elles sont si communes, que même si un système n'offrait pas une fonction /bin/sh
il comprendrait probablement encore #!/bin/sh
et savoir quoi en faire et que ce ne soit que pour la compatibilité avec le code existant.
Mais pour les interpréteurs plus modernes, non standard et optionnels comme Perl, PHP, Python ou Ruby, il n'est pas vraiment spécifié où ils doivent être situés. Ils peuvent être dans /usr/bin
mais ils peuvent aussi bien être dans /usr/local/bin
ou dans une branche hiérarchique complètement différente ( /opt/...
, /Applications/...
etc.). C'est pourquoi ces derniers utilisent souvent le #!/usr/bin/env xxx
syntaxe shebang.
11 votes
Voir cette question y ma réponse .
6 votes
Qui peut me dire pourquoi cette question est fermée, alors que "lié à la programmation ou au développement de logiciels" ne l'est pas ?
1 votes
Je suis d'accord pour dire qu'il ne s'agit pas d'un hors-sujet, mais il s'agit probablement d'un doublon de plusieurs autres questions telles que celui-ci .
22 votes
Cette question n'aurait pas dû être marquée comme hors-sujet. Il suffit que 5 personnes ayant un score supérieur à 3000 la marquent comme "on-topic" pour qu'elle puisse être rouverte. Il s'agit d'une question - spécifiquement sur la programmation.
1 votes
@DanijelJ : Je suis d'accord que ce n'est pas hors sujet, mais c'est un doublon. Nous pourrions voter pour la réouverture et ensuite voter pour la fermer à nouveau comme un doublon. Cela ne semble pas en valoir la peine.
1 votes
En rapport : Pourquoi #!/usr/bin/env bash est-il supérieur à #!/bin/bash ? à SO
4 votes
Je suis choqué. Choqué de constater que la documentation de Linux est truffée de tautologies. xkcd.com/703 git-man-page-generator.lokaltog.net
2 votes
Une différence majeure est que, selon le système,
#!/usr/bin/bash
ne fonctionne pas . Sur mon système (Ubuntu 17.04),bash
es/bin/bash
et il n'y a pas de/usr/bin/bash
. La distinction entre/bin
y/usr/bin
est largement arbitraire. Et pour ajouter à la frivolité, la plupart des systèmes mettent laenv
dans/usr/bin
mais ce n'est pas garanti.0 votes
Puis faites un lien symbolique. Mais c'était vraiment dans le sujet.