Le $PATH vers la lumière

L'installation de logiciels sur notre machine est souvent un processus pénible et semé d'embûches. Mieux connaître $PATH facilitera notre vie et nous évitera quelques crises, grâce au Frenchie Olivier Lacan.

Par

L’installation des logiciels open source est souvent pénible, mais un processus d'installation un peu compliqué — même lorsqu'il semble nous éloigner du but (résoudre des problèmes au moyen dudit logiciel) — constitue une bonne opportunité d’apprivoiser l’un de nos principaux outils de travail : la ligne de commande.

La ligne de commande (command line) repousse pas mal de gens — elle est souvent considérée comme la technologie des hackers et des “sorciers de l’informatique”. La réalité n’est pas aussi cool, il s’agit en fait d’un ensemble d’outils ridiculement simples créés dans les années 70 par les employés de Bell (aujourd’hui AT&T) pour réaliser les tâches les plus basiques. C’est à peu près aussi “space-age” que votre four à micro-ondes.

Mais la ligne de commande est extrêmement utile et puissante, et vous donnera parfois l’impression de passer de la construction manuelle à la construction industrielle. Avec quelques concepts et quelques métaphores, nous allons essayer de jeter un peu de lumière dans les recoins les plus sombres de notre ligne de commande.

Parmi ces concepts, l’un des plus importants est le Chemin d'Accès (Path).

De nombreux frameworks, pré-processeurs CSS, bibliothèques JavaScript et autres outils de développement reposent sur Ruby ou sur Node.js pour leur installation sur votre machine. Bower est l’un de ces outils. Invariablement, ces outils vous conduiront à interagir avec le Chemin — parce que le Chemin doit connaître l’ensemble des outils que vous installez pour votre environnement de développement, afin que votre ligne de commande fonctionne convenablement.

Plus vous utiliserez la ligne de commande et plus il y a de chances que vous rencontriez des problèmes avec le Chemin. Avant que vous ne perdiez trop de temps ou que vous ne vous en preniez à votre machine, passons en revue les bases de l’utilisation du Chemin.

Une humble petite variable

$PATH, comme le dénotent son préfixe $ et ses majuscules criardes, est une variable d’environnement Unix. À l’intérieur de cette variable est enregistrée une liste de chemins de dossiers, séparés par des :, qui ressemble à ceci :

/root/directory/binary:/root/other_directory/other_binary

Si vous êtes curieux de savoir quelles autres variables d’environnement existent dans votre système, vous pouvez taper env dans la ligne de commande. Faites Enter et vous verrez la liste de toutes les variables d’environnement présentes.

Puisque $PATH est une variable, elle peut être modifiée comme vous le souhaitez, à la volée. Par exemple, vous pouvez taper ceci dans votre ligne de commande :

$ export PATH=banana

Que fait cette commande ? Eh bien, après l’avoir tapée, essayez de lancer n’importe quelle commande basique (par exemple ls pour lister le contenu d’un dossier) et vous obtiendrez un message -bash: ls: command not found alors que ls fonctionnait jusqu’ici sans problème…

Ce sabotage sournois nous aide à comprendre que sans contenu dans notre $PATH nous nous retrouvons… comme des bananes.

Mais pourquoi ? Eh bien parce que comme le font de nombreux chemins de chargement (y compris dans les langages de programmation et dans les frameworks comme Rails), ce Path détermine ce qui peut être exécuté dans votre ligne de commande. Si cette dernière ne peut rien trouver qui corresponde au nom que vous avez entré, elle ne peut pas l’exécuter.

Ah ! à propos : il suffit de quitter votre application de ligne de commande pour restaurer toutes vos commandes. C’était un sabotage temporaire. Mais faites attention de ne jamais sauvegarder ce genre de blagues dans votre ~/.bash_profile, ça pourrait mal se terminer.

Le conte des mille et un binaires

Dans Unix, certains programmes exécutables sont appelés binaires (binaries). Honnêtement, ce n’est pas un nom génial, il se focalise sur leur format plutôt que sur leur fonction. Quand vous écrivez un programme Unix, vous avez parfois besoin de compiler la source avant de pouvoir l’exécuter. Ce processus de compilation est ce qui crée le binaire. Plutôt que d’utiliser du texte (comme votre code source), ces fichiers utilisent un format binaire pour faciliter le traitement des instructions par les ordinateurs.

Unix comporte de nombreux dossiers dans lesquels enregistrer les binaires. Vous pouvez voir quel dossier est le dossier par défaut de stockage des binaires dans le fichier /etc/paths, pour cela il suffit d’utiliser la commande cat qui permet d’imprimer le contenu d’un fichier :

$ cat /etc/paths 
/usr/bin 
/bin 
/usr/sbin 
/sbin 
/usr/local/bin

Ce fichier contient un dossier par ligne. Les chemins sont listés dans un ordre signifiant. Lorsqu’un binaire est trouvé dans un chemin, il est chargé. Si un binaire portant le même nom est trouvé par la suite dans un autre chemin, il est ignoré. Autrement dit, les chemins listés les premiers prennent le pas sur ceux qui les suivent.

Voilà pourquoi il est si commun de rencontrer des problèmes lorsqu’on essaie d’installer un binaire pour quelque chose qui existe déjà dans notre système. Dans le cas d’OS X, si vous essayez d’installer une version de Git différente de celle déjà présente dans le système, vous serez confronté à ce genre de problème. Et c’est bien dommage, parce que Git 2.0 est vraiment super.

Si je fais cd (change directory) dans /usr/bin — un dossier courant pour stocker les binaires — et que je fais ls j’aurai plus de 1.000 résultats. Ça ne m’aide pas beaucoup. Ceci dit, si j’utilise grep avec ls | grep git, je peux filtrer les résultats de la commande ls en ne conservant que ceux qui contiennent “git”.

$ ls | grep git 
git
git-cvsserver
git-receive-pack
git-shell 
git-upload-archive 
git-upload-pack

...et bien sûr il y a un binaire pour Git à l’intérieur de /usr/bin. Une installation propre d’OS X devrait retourner /usr/bin/git lorsque vous faites which git :

$ which git 
/usr/local/bin/git

Alors pourquoi mon résultat est-il différent ? En utilisant l’option -a, nous pouvons avoir une idée de ce qui se passe :

$ which -a git
/usr/bin/git
/usr/local/bin/git

Ceci me dit qu’il y a deux versions de Git sur mon système. Mais seule la première version est utilisée quant j’exécute les commandes git dans ma ligne de commande, la seconde est ignorée.

Changer de chemins

J’ai installé ma propre version de Git à l’aide d’un package manager pour OS X appelé Homebrew, parce que j’aime bien pouvoir contrôler les outils que j’utilise au quotidien et les mettre à jour quand je le veux. Je pourrais certes mettre à jour le Git installé dans le système, mais je n’ai aucune idée des applications ou des autres binaires qui en dépendent.

Nous avons vu que les fichiers binaires sont sélectionnés dans l’ordre où ils apparaissent, alors pourquoi ne changerions-nous pas cet ordre ?

À l’intérieur du fichier /etc/paths, je peux voir que le dossier /usr/local/bin, dans lequel se trouve ma version de Git installée avec Homebrew, arrive en dernier. Cela signifie que le binaire git qui se trouve dans /usr/bin aura la priorité et mon git sera ignoré. Il faut changer cela.

Pour ce faire, vous pourriez essayer de modifier l’ordre dans /etc/paths de façon à ce qu’il corresponde à vos besoins, en mettant /usr/local/bin tout en haut, et la version Homebrew serait chargée en premier. Mais malgré le nombre de fois où vous verrez ce conseil répété dans les discussions sur Stack Overflow, ne le faites pas. Jamais. Les configurations enregistrées dans /etc/ affectent le système tout entier. Elles ne sont pas censées être modifiées par les utilisateurs individuels (même si vous êtes le seul utilisateur de la machine), et vous pourriez créer des problèmes inattendus en bricolant de la sorte. Par exemple, certains services utilisés par OS X pourraient reposer sur l’ordre original de /etc/paths.

C’est le $PATH que vous devez modifier, dans votre environnement, en utilisant votre .bash_profile — celui qui est enregistré dans /Users/votrenomdutilisateur/.bash_profile.

Pour vous assurer que /usr/local/bin soit recherché en premier, il suffit d’inclure ce qui suit dans votre .bash_profile (par exemple pour moi dans /Users/olivierlacan/.bash_profile) :

export PATH=/usr/local/bin:$PATH

Cette ligne exporte une nouvelle variable d’environnement $PATH en imprimant celle qui existe actuellement et en plaçant juste avant le chemin /usr/local/bin. Après avoir enregistré votre ~/.bash_profile et redémarré votre ligne de commande, voici ce que vous devriez voir lorsque vous faite echo sur le $PATH :

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

Comme vous pouvez le voir, /usr/local/bin est mentionné deux fois dans le $PATH, et ce n’est pas un problème. Comme il est mentionné en premier, tous les binaires chargés à ce moment seront ignorés lorsqu’ils sont rencontrés par la suite. Honnêtement, j’aimerais qu’il existe une façon simple et sûre de changer l’ordre des chemins, mais la plupart des solutions que je connais sont un peu trop complexes.

Maintenant que vous avez changé le $PATH, vous pouvez vérifier que le bon binaire est appelé quand vous utilisez la commande git :

$ which git 
/usr/local/bin/git 

$ git --version 
git version 2.0.0
/usr/bin/git --version git version 1.8.5.2 (Apple Git-48)

Et voilà. Git 2.0.0 (la version installée par Homebrew) répond maintenant à la commande git, et la version installée par Apple est reléguée à l’arrière. Si vous préférez ne pas utiliser git 2.0.0, il suffit de le désinstaller et la version par défaut prendra le relais.

Protégez votre chemin

Tout un tas de services pour les développeurs et les designers injecteront automatiquement du code dans votre .bash_profile lors de leur installation, souvent sans même le mentionner. Si vous trouvez des chemins bizarres listés dans votre profil, cela peut expliquer que le chargement d’une nouvelle session (ce qui arrive lorsque vous ouvrez une nouvelle fenêtre ou onglet de la ligne de commande) prenne plus de temps que prévu : un $PATH boursoufflé peut prendre du temps à se charger.

Voici mon chemin aujourd’hui :

/Users/olivierlacan/.rbenv/shims:/Users/olivierlacan/.rbenv/bin:/usr/local/bin:/usr/local/heroku/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/MacGPG2/bin

C’est un peu dur à lire, alors j’ai tendance à subdiviser l’affichage en lignes distinctes. C’est facile à faire avec la commande tr (traduire les caractères : les : sont traduits en \n, c’est à dire en retour à la ligne) :

$ echo $PATH | tr ':' '\n'
/Users/olivierlacan/.rbenv/shims
/Users/olivierlacan/.rbenv/bin
/usr/local/bin
/usr/local/heroku/bin
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin
/opt/X11/bin
/usr/local/MacGPG2/bin

Cela fait beaucoup en effet, et c’est bien plus simple à lire verticalement. Essayez sur votre machine, et si vous ne savez pas pourquoi une de ces lignes est dans votre $PATH, tentez de savoir pourquoi.

Maintenant que vous connaissez votre Chemin, à quoi il ressemble lorsqu’il est propre, comment le modifier comme il faut, et comment vérifier qu’il correspond à vos outils, il y a des chances que vous ne passerez plus des heures à retrouver votre chemin : celui que vous utilisez pour construire des choses pour les autres.


Intéressé par les outils de développement ? Retrouvez une liste des meilleurs articles et ressources du web.

Tous les articles sur les outils de développement dans La Cascade.


original paru le dans A List Apart.

Sur l’auteur : est développeur chez Code School, spécialiste de Ruby. Il écrit fréquemment sur toutes sortes de sujets et travaille à rendre le monde de l'open source plus accueillant. On peut le suivre sur son site, sur Github ainsi que sur Twitter.

Traduit avec l’aimable autorisation de A List Apart et de l’auteur.
Copyright A List Apart © 2014.