Les entrées en double dans $ PATH sont un problème?


45

Je source bashrc de quelques-uns de mes amis. Je finis donc par avoir des entrées en double dans ma variable $ PATH. Je ne suis pas sûr que ce soit le problème pour les commandes dont le démarrage est long. Comment fonctionne $ PATH en interne dans bash? Avoir plus de PATHS ralentit-il mon temps de démarrage?




Réponses:


42

Avoir plus d'entrées $PATHne ralentit pas directement votre démarrage, mais cela ralentit à chaque fois que vous exécutez une commande particulière dans une session shell (pas à chaque fois que vous exécutez la commande, car bash conserve un cache). Le ralentissement est rarement perceptible sauf si vous avez un système de fichiers particulièrement lent (par exemple, NFS, Samba ou un autre système de fichiers réseau, ou sur Cygwin).

Les entrées en double sont également un peu gênantes lorsque vous examinez votre $PATHvisuel, vous devez parcourir plus cruellement.

Il est assez facile d'éviter d'ajouter des entrées en double.

case ":$PATH:" in
  *":$new_entry:"*) :;; # already there
  *) PATH="$new_entry:$PATH";; # or PATH="$PATH:$new_entry"
esac

Note secondaire: rechercher le script shell de quelqu'un d'autre signifie exécuter le code qu'il a écrit. En d'autres termes, vous donnez à vos amis l'accès à votre compte quand ils le souhaitent.

Remarque secondaire: .bashrcn’est pas le bon endroit pour définir $PATHou toute autre variable d’environnement. Les variables d'environnement doivent être définies dans ~/.profile. Voir Quels fichiers de configuration doivent être utilisés pour configurer les variables d'environnement avec bash? , La différence entre .bashrc et .bash_profile .


8
+1: ne peut pas souligner que "donner à vos amis l'accès à votre compte" suffisamment d'emphase. Même s'il n'y a aucune tentative de vous faire du mal, leur scénario pourrait être exactement ce dont ils ont besoin et manger quand même votre déjeuner quand vous le sourcez.
msw

Un problème possible avec cette solution est que si $ new_entry est déjà la première entrée de PATH, le ": $ new_entry:" ne correspondra pas. J'ai corrigé cela dans mon profil en excluant l'initiale ':' deux points.
Jeff Bauer

@JeffBauer Je ne vois pas le problème. J'utilise case :$PATH:et pas case $PATHpour qu'il corresponde même si l'entrée est première ou dernière.
Gilles, arrête de faire le mal,

31

J'ai vu des personnes nettoyer les doublons de leur variable PATH en utilisant awket quelque chose comme ceci:

PATH=$(printf "%s" "$PATH" | awk -v RS=':' '!a[$1]++ { if (NR > 1) printf RS; printf $1 }')

Vous pouvez essayer d’ajouter cela à votre propre base et vous assurer que vous sourcez les autres fichiers quelque part avant de l’exécuter.

Une alternative serait d'utiliser l'pathmerge utilitaire.

En ce qui concerne votre problème de vitesse, cela n’affectera pas le temps de démarrage du shell de manière significative, mais vous gagnerez peut-être du temps pour compléter les commandes, en particulier lorsque la commande n’est pas trouvée dans le chemin et qu’elle effectue des recherches répétées dans le même sens. dossiers à la recherche.

Un mot sur la sécurité: Vous devriez vraiment écouter les avertissements de Gilles sur la sécurité ici. En recherchant un fichier appartenant à un autre utilisateur, vous donnez un laissez-passer gratuit à ces utilisateurs pour qu'ils exécutent leur propre code en tant qu'utilisateur chaque fois que vous démarrez un shell. Si vous ne faites pas confiance à ces utilisateurs avec votre mot de passe, vous ne devriez pas rechercher leurs fichiers shell.


6
J'aime le awk one-liner, mais il affiche un ORS final: ':'. Alors je l'ai modifié pour lirePATH=$(echo "$PATH" | awk -v RS=':' -v ORS=":" '!a[$1]++{if (NR > 1) printf ORS; printf $a[$1]}')
gkb0986

La fuite :n'est pas qu'une question esthétique. Cela revient à ajouter .à votre chemin, ce qui est potentiellement dangereux.
Wisbucky

J'ai modifié la réponse pour inclure le correctif de gkb0986.
Tim Lesher

@TimLesher La raison pour laquelle je n'avais jamais modifié cette réponse, c'est que cela ne fonctionne pas pour moi ... et l'original sans cela fonctionne (notamment en ne laissant pas de séparateur final. Je ne sais pas quelle est la différence .
Caleb

1
@ gkb0986 Cette solution échoue quand même si le chemin contient un espace d'échappement, tel que PATH = / bin: / foo \ bar: / usr / bin. J'ai trouvé une variante qui évite cela à l' adresse unix.stackexchange.com/a/124517/106102
maharvey67

13

Basé sur la réponse de @Gilles, vous pouvez l'envelopper dans une fonction pour minimiser la frappe:

function addToPATH {
  case ":$PATH:" in
    *":$1:"*) :;; # already there
    *) PATH="$1:$PATH";; # or PATH="$PATH:$1"
  esac
}

addToPATH /Applications/AIRSDK_Compiler/bin
addToPATH ~/.local/lib/npm/bin

1
Réponse la plus pratique (de haut niveau, peut-être).
ijoseph

3

Seule la première correspondance de $PATHest exécutée, les entrées suivantes ne sont pas traitées par la suite. C'est pourquoi vous devez parfois modifier l'ordre des entrées dans $PATHvotre environnement afin que votre environnement se comporte comme prévu.

Pour répondre à votre question: cela ne devrait pas être la cause d'un démarrage lent.


1
Mais cela prend plus de temps lorsque je tape une commande qui n’existe pas. Il recherchera la commande deux fois dans le même dossier.
Bali

@balki Vous voulez dire terminer une commande avec TAB? Dans ce cas, vous devriez vérifier si votre définition complète ne ressemble pas complete -c which -a. Vous devez supprimer le -aparamètre. Vous pouvez vérifier que en exécutant la commande: complete | grep which.
Rajish

Cela pourrait toujours être un problème si il recherche dans le même répertoire qu'il ne se trouve pas plusieurs fois avant de le trouver.
Random832

-1

Pour éviter les entrées en double dans mon PATH, je devais mettre les éléments suivants dans BOTH ~ / .bash_profile et ~ / .bashrc:

PATH=$(echo $(sed 's/:/\n/g' <<< $PATH | sort | uniq) | sed -e 's/\s/':'/g')

L'inconvénient principal est qu'il trie les entrées de PATH, mais je pense pouvoir vivre avec cela.


L'ordre de la recherche PATH est assez important.
Steven Shaw
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.