15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer
08.10.2024

La commande `which` sous Linux : Guide technique complet avec exemples

La commande `which` sous Linux localise le chemin absolu d’un exécutable en parcourant les répertoires listés dans la variable d’environnement `PATH` et en retournant la première correspondance trouvée. C’est un utilitaire adjacent à POSIX utilisé quotidiennement par les administrateurs système, les développeurs et les ingénieurs DevOps pour vérifier les emplacements des binaires, auditer les environnements d’exécution et déboguer les conflits liés au PATH.

Lorsque vous exécutez `which python3`, le shell ne parcourt pas l’ensemble du système de fichiers — il traverse uniquement la liste de répertoires délimitée par des deux-points stockée dans `$PATH`, de gauche à droite, et s’arrête à la première correspondance. Ce comportement est à la fois sa plus grande force et sa limitation la plus importante à comprendre.

Syntaxe de base

“`bash

which [options] command_name [command_name …]

“`

  • `[options]` — Options facultatives qui modifient le comportement de la sortie (détaillées ci-dessous).
  • `command_name` — Un ou plusieurs noms d’exécutables que vous souhaitez localiser.

Fonctionnement interne de `which`

Lorsque vous invoquez `which`, il lit la valeur actuelle de la variable d’environnement `PATH`, la divise sur les délimiteurs `:`, et itère à travers chaque répertoire dans l’ordre. Pour chaque répertoire, il vérifie si un fichier correspondant au nom de la commande existe et possède le bit exécutable (permission `x`). La première correspondance est affichée sur la sortie standard.

Cela signifie que `which` dépend entièrement de l’état d’exécution de `$PATH`. Si votre `PATH` est mal configuré — par exemple, un répertoire personnalisé apparaît après `/usr/bin` au lieu d’avant — `which` reflétera exactement cette mauvaise configuration, ce qui est précisément pourquoi il est utile pour le débogage.

Pour inspecter votre `PATH` actuel :

“`bash

echo $PATH

Example output:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

“`

Cas d’utilisation principaux et exemples

Exemple 1 : Localiser un seul exécutable

L’utilisation la plus fondamentale est de trouver où réside un binaire :

“`bash

which python3

“`

“`

/usr/bin/python3

“`

Cela confirme que lorsque vous tapez `python3`, le système exécute `/usr/bin/python3`. Si vous avez compilé une version personnalisée et l’avez placée dans `/opt/python3.12/bin/`, mais que ce répertoire n’est pas dans `PATH`, `which` ne le trouvera pas.

Exemple 2 : Interroger plusieurs commandes en une seule passe

Vous pouvez passer plusieurs noms de commandes en une seule invocation, ce qui est efficace lors de l’audit d’un environnement de build :

“`bash

which python3 gcc git curl wget

“`

“`

/usr/bin/python3

/usr/bin/gcc

/usr/bin/git

/usr/bin/curl

/usr/bin/usr/bin/wget

“`

Cela est particulièrement utile dans les scripts de validation de pipeline CI/CD, où vous devez confirmer que tous les outils requis sont présents avant le début d’un build.

Exemple 3 : Découvrir toutes les instances avec `-a`

L’option `-a` demande à `which` de continuer la recherche après la première correspondance et de signaler chaque instance trouvée dans tous les répertoires `PATH` :

“`bash

which -a python3

“`

“`

/usr/bin/python3

/usr/local/bin/python3

“`

C’est essentiel dans les environnements où plusieurs versions de Python sont installées — par exemple, un Python système à `/usr/bin/python3` et une version gérée par pyenv à `/usr/local/bin/python3`. Le binaire qui apparaît en premier dans `PATH` est celui qui est exécuté. Si la mauvaise version est active, cette sortie vous indique exactement l’origine du conflit.

Cas limite réel : Sur les serveurs exécutant à la fois un Node.js fourni par la distribution et un Node.js géré par nvm, `which -a node` révèle fréquemment deux ou trois chemins conflictuels. La résolution nécessite de réordonner les entrées `PATH` dans `.bashrc` ou `.zshrc`, et non de réinstaller le logiciel.

Exemple 4 : Comportement de résolution des alias

Le comportement de `which` avec les alias dépend fortement du shell et de l’implémentation spécifique de `which` installée sur le système.

Sur de nombreuses distributions Linux, `which` est un binaire externe autonome (pas un built-in du shell), il n’a donc pas accès à la table d’alias du shell courant. Cependant, sur les systèmes où `which` est implémenté comme une fonction shell ou un alias lui-même (courant dans les configurations zsh), il peut résoudre les alias :

“`bash

alias ls='ls –color=auto'

which ls

“`

Sur un système zsh avec le `which` basé sur des fonctions :

“`

ls: aliased to ls –color=auto

“`

Sur un système bash avec le binaire externe `which` :

“`

/bin/ls

“`

Cette incohérence est une source de confusion bien connue et est l’une des principales raisons pour lesquelles les administrateurs expérimentés préfèrent `type` ou `command -v` dans les scripts (discuté ci-dessous).

Exemple 5 : Utiliser `which` dans la logique conditionnelle des scripts

Un modèle courant dans les scripts shell consiste à utiliser `which` pour vérifier une dépendance avant de continuer :

“`bash

if ! which docker > /dev/null 2>&1; then

echo "Docker is not installed or not in PATH. Aborting."

exit 1

fi

“`

Cependant, l’approche plus portable et conforme à POSIX pour les scripts est `command -v` :

“`bash

if ! command -v docker > /dev/null 2>&1; then

echo "Docker not found."

exit 1

fi

“`

La distinction est importante lors de l’écriture de scripts destinés à s’exécuter sur plusieurs distributions ou shells.

`which` vs. `type` vs. `command -v` : Une comparaison technique

Ces trois outils répondent à des besoins qui se chevauchent mais sont distincts. Choisir le mauvais outil pour le travail entraîne des bugs subtils, notamment dans les scripts shell.

Fonctionnalité`which``type``command -v`
Localise les binaires externesOuiOuiOui
Résout les alias shellDépend de l’implémentationOui (toujours)Oui (toujours)
Résout les fonctions shellNonOuiOui
Identifie les built-ins shellNonOuiOui
Conforme à POSIXNonOuiOui
Fonctionne de manière fiable dans les scriptsRisquéRisqué (built-in bash)Recommandé
Format de sortieChemin uniquementChaîne descriptiveChemin ou définition
Recherche toutes les entrées PATH (équivalent `-a`)Oui (avec `-a`)Oui (avec `-a`)Non
Binaire externe (pas un built-in)OuiNon (built-in)Non (built-in)

Conseils pratiques :

  • Utilisez `which` de manière interactive dans le terminal lorsque vous avez besoin d’une recherche rapide de chemin.
  • Utilisez `type -a` lorsque vous souhaitez voir toutes les formes que prend une commande (alias, fonction, built-in et binaire).
  • Utilisez `command -v` dans les scripts shell de production pour la portabilité POSIX.

`type` en action

“`bash

type -a python3

“`

“`

python3 is /usr/bin/python3

python3 is /usr/local/bin/python3

“`

“`bash

type ls

“`

“`

ls is aliased to `ls –color=auto'

“`

`command -v` en action

“`bash

command -v git

“`

“`

/usr/bin/git

“`

“`bash

command -v ll

“`

“`

ll: aliased to ls -alF

“`

Scénarios de débogage pratiques

Déboguer une mauvaise version de Python

Un développeur signale que `python3 –version` retourne `3.9.x` mais qu’il a installé `3.11` via un build personnalisé. La séquence de diagnostic :

“`bash

which python3 # Shows the first match

which -a python3 # Shows all matches

echo $PATH # Reveals directory ordering

ls -la /usr/local/bin/python3 # Checks if the custom build is symlinked correctly

“`

La correction est presque toujours soit un lien symbolique manquant, soit un problème d’ordre `PATH` dans le fichier d’initialisation du shell.

Diagnostiquer une commande manquante après installation

Si `which curl` ne retourne aucune sortie, le binaire n’est soit pas installé, soit installé dans un répertoire hors `PATH`. Distinguez ces cas :

“`bash

which curl # No output = not in PATH

find /usr -name curl -type f 2>/dev/null # Search for the binary outside PATH

apt list –installed 2>/dev/null | grep curl # Check package manager

“`

Vérifier les chemins des outils avant le déploiement

Lors de la configuration d’un nouvel environnement VPS Hosting, une liste de contrôle standard avant déploiement devrait inclure l’exécution de `which -a` sur chaque binaire critique dont dépend votre application. Cela permet de détecter la dérive d’environnement entre le développement, la mise en scène et la production avant qu’elle ne provoque des échecs d’exécution.

Limitations connues de `which`

Comprendre ces limitations évite les mauvais diagnostics dans les environnements complexes :

  • Portée `PATH` uniquement : `which` est aveugle à tout exécutable non accessible via `$PATH`. Les outils installés dans des répertoires locaux à l’utilisateur comme `~/.local/bin` ne seront trouvés que si ce répertoire est dans `PATH`.
  • Aucune connaissance des built-ins shell : Les commandes comme `cd`, `echo`, `alias` et `source` sont des built-ins shell. `which cd` ne retournera rien ou un chemin vers un binaire `cd` externe rarement utilisé, donnant un résultat trompeur.
  • Tables d’alias spécifiques au shell : `which` en tant que binaire externe ne peut pas lire la table d’alias du shell appelant. Cela le rend peu fiable pour l’introspection des alias dans bash.
  • Transparence des liens symboliques : `which` signale le chemin du lien symbolique, pas la cible résolue. Si `/usr/bin/python3` est un lien symbolique vers `/usr/bin/python3.11`, `which python3` affiche `/usr/bin/python3`. Utilisez `readlink -f $(which python3)` pour résoudre la chaîne complète.
  • Contexte `sudo` : L’exécution d’une commande avec `sudo` utilise le `PATH` de root, qui peut différer significativement du `PATH` de votre utilisateur. `which node` en tant qu’utilisateur ordinaire peut retourner un chemin différent de `sudo which node`.

Modèles avancés

Résoudre la chaîne complète de liens symboliques

“`bash

readlink -f $(which python3)

Output: /usr/bin/python3.11

“`

Vérifier les permissions d’exécution en même temps que le chemin

“`bash

ls -la $(which nginx)

Output: -rwxr-xr-x 1 root root 1234567 Jan 10 2024 /usr/sbin/nginx

“`

Combiner avec `xargs` pour une inspection par lots

“`bash

echo "python3 gcc git" | xargs -n1 which

“`

Utiliser dans les scripts de validation d’environnement

Sur un Serveur Dédié exécutant une pile d’applications complexe, un script de validation au démarrage pourrait ressembler à ceci :

“`bash

#!/bin/bash

REQUIRED_BINS="nginx php-fpm mysql redis-cli composer"

MISSING=0

for bin in $REQUIRED_BINS; do

if ! command -v "$bin" > /dev/null 2>&1; then

echo "MISSING: $bin"

MISSING=$((MISSING + 1))

else

echo "OK: $bin -> $(which $bin)"

fi

done

[ "$MISSING" -gt 0 ] && exit 1

exit 0

“`

Notes sur le comportement spécifique aux shells

Le comportement de `which` n’est pas uniforme dans tous les environnements Linux :

  • Bash : `which` est généralement un binaire externe (`/usr/bin/which`). Il ne voit pas les alias ou fonctions bash à moins qu’ils ne soient exportés.
  • Zsh : De nombreuses configurations zsh fournissent `which` comme une fonction shell built-in qui résout bien les alias et les fonctions, rendant sa sortie plus riche mais aussi différente du comportement de bash.
  • Fish shell : Fish possède son propre équivalent `which` intégré, et son système d’alias (appelé `functions`) est géré différemment.
  • Environnements Alpine Linux / BusyBox : L’utilitaire `which` est fourni par BusyBox et peut avoir un ensemble de fonctionnalités réduit par rapport au paquet GNU `which`.

Cette variabilité est particulièrement pertinente lors de la gestion d’applications conteneurisées ou de la configuration de Panneaux de contrôle VPS où le shell sous-jacent peut différer de votre environnement de développement local.

Considérations de sécurité

Dans les environnements sensibles à la sécurité, `which` peut être utilisé comme outil d’audit léger :

  • Vérifiez que les binaires privilégiés comme `sudo`, `su` ou `passwd` se résolvent vers les chemins système attendus et non vers des répertoires accessibles en écriture par l’utilisateur apparaissant plus tôt dans `PATH`.
  • Détectez les tentatives de détournement de PATH : si `which ls` retourne `/home/user/bin/ls` au lieu de `/bin/ls`, un binaire malveillant peut avoir été injecté.

“`bash

Audit critical system binaries

for cmd in sudo su passwd ssh scp; do

echo "$cmd -> $(which $cmd)"

done

“`

C’est une étape standard lors du durcissement d’un serveur qui hébergera des Certificats SSL ou gérera une terminaison TLS sensible, où l’intégrité des binaires est non négociable.

Lors de la gestion d’environnements d’Hébergement Web Mutualisé avec plusieurs utilisateurs, vérifier que les répertoires accessibles en écriture par les utilisateurs n’apparaissent pas avant les répertoires système dans le `PATH` de tout utilisateur est un contrôle de sécurité important.

Matrice de décision : Quel outil utiliser et quand

ScénarioOutil recommandé
Recherche rapide de chemin en mode interactif`which`
Script : vérifier si une commande existe`command -v`
Identifier si une commande est un alias ou une fonction`type`
Trouver toutes les instances dans PATH`which -a` ou `type -a`
Résoudre les liens symboliques vers le binaire final`readlink -f $(which …)`
Auditer les détournements de PATH`which` + inspection manuelle du PATH
Scripts portables multi-shells`command -v`

Points clés techniques

  • `which` recherche dans `$PATH` de gauche à droite et retourne la première correspondance exécutable — l’ordre des entrées `PATH` détermine directement quel binaire s’exécute.
  • L’option `-a` est essentielle lorsque plusieurs versions d’un outil coexistent ; ne supposez jamais qu’une seule instance existe sans vérifier.
  • N’utilisez pas `which` dans les scripts shell de production — utilisez `command -v` pour la conformité POSIX et un comportement cohérent entre bash, dash et zsh.
  • `which` ne peut pas voir les built-ins shell, les fonctions ou les alias définis dans la session shell courante lorsqu’il s’exécute en tant que binaire externe.
  • Faites toujours suivre un résultat de `which` par `readlink -f` lorsque des liens symboliques sont impliqués pour identifier le binaire réellement exécuté.
  • Dans les environnements multi-utilisateurs ou conteneurisés, `PATH` diffère entre les utilisateurs et entre les contextes `sudo` et non-`sudo` — vérifiez toujours dans le bon contexte.
  • Le détournement de PATH via des répertoires accessibles en écriture par l’utilisateur ajoutés en tête de `$PATH` est un vecteur d’attaque réel ; `which` est un outil d’audit rapide de première ligne contre celui-ci.

Foire aux questions

Quelle est la différence entre `which` et `whereis` ?

`which` recherche uniquement dans `$PATH` les exécutables. `whereis` recherche dans un ensemble plus large de répertoires système prédéfinis le binaire, sa page de manuel et ses fichiers source simultanément. Utilisez `whereis` lorsque vous avez besoin de localiser la documentation ou les sources en même temps que le binaire.

Pourquoi `which cd` ne retourne-t-il rien ?

`cd` est un built-in shell, pas un exécutable externe. Comme `which` ne parcourt que `$PATH` à la recherche de fichiers avec permission d’exécution, il ne peut pas trouver les commandes built-in. Utilisez plutôt `type cd`, qui signalera correctement `cd is a shell builtin`.

`which` peut-il me dire quelle version d’un programme est installée ?

Non. `which` retourne uniquement le chemin. Pour obtenir la version, redirigez le résultat : `$(which python3) –version` ou simplement `python3 –version`. Le chemin fourni par `which` vous aide à confirmer que vous interrogez le bon binaire.

Pourquoi `which python3` retourne-t-il un résultat différent lorsque j’utilise `sudo` ?

`sudo` exécute les commandes avec l’environnement de root, y compris le `PATH` de root, qui est généralement plus restrictif que celui d’un utilisateur ordinaire. Les répertoires comme `~/.local/bin` ou les chemins nvm/pyenv ajoutés au `.bashrc` d’un utilisateur sont absents du `PATH` de root. Testez toujours avec `sudo which python3` séparément lors du débogage d’une exécution avec élévation de privilèges.

`which` est-il disponible sur macOS ?

Oui, macOS inclut `which` dans son environnement utilisateur dérivé de BSD. Cependant, la version macOS ne prend pas en charge l’option `-a` dans toutes les versions plus anciennes. Sur macOS moderne avec Homebrew, vous pouvez avoir le GNU `which` installé aux côtés de la version système. Utilisez `type -a which` sur macOS pour voir quelle implémentation est active.

15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer