Comment vider le cache de Bash des chemins d'accès aux exécutables?

257

Lorsque j'exécute un programme sans spécifier le chemin complet de l'exécutable, et que Bash doit rechercher les répertoires $PATHpour trouver le binaire, il semble que Bash se souvienne du chemin dans une sorte de cache. Par exemple, j'ai installé une version de Subversion à partir de la source /usr/local, puis tapé svnsync helpà l'invite Bash. Bash a localisé le binaire /usr/local/bin/svnsyncpour "svnsync" et l'a exécuté. Puis, lorsque j'ai supprimé l'installation de Subversion /usr/localet que je l'ai ré-exécuté svnsync help, Bash a répondu:

bash: /usr/local/bin/svnsync: No such file or directory

Mais lorsque je démarre une nouvelle instance de Bash, celle-ci est trouvée et exécutée /usr/bin/svnsync.

Comment effacer le cache des chemins d'accès aux exécutables?

Daniel Trebbien
la source
7
fonctionnalité stupide jamais
Romeno

Réponses:

323

bashmet en cache le chemin complet d'une commande. Vous pouvez vérifier que la commande que vous essayez d'exécuter est hachée avec la typecommande:

$ type svnsync
svnsync is hashed (/usr/local/bin/svnsync)

Pour effacer tout le cache:

$ hash -r

Ou juste une entrée:

$ hash -d svnsync

Pour plus d'informations, consultez help hashet man bash.

Tobu
la source
15
@ Daniel Il est intéressant d'ajouter que, dans bash, vous pouvez utiliser la commande "type de commande " pour savoir de quel type de commande il s'agit - si votre commande est hachée, "type" vous le dira. Il est également utile de savoir si quelque chose est un shell intégré ou un alias.
lunchmeat317
4
En tant que FYI, pour modifier le chemin PATH mis en cache s'il est en cours d'exécution csh, la commande est rehash.
Kurtm
La rehashcommande ci-dessus fonctionne également pour zsh.
Neil Traft
Pour une réponse plus complète, voir unix.stackexchange.com/questions/86012/…
Ioannis Filippidis
4
Dans une commande, le rehashing sélectif peut être invoqué par hash svnsync.
Ioannis Filippidis
25

Pour effacer une seule entrée, vous avez besoin d'un indicateur différent:

hash -d svnsync

L' -rindicateur ne prend pas de paramètre et supprimera toujours tout le cache.
(Au moins à la bash 3.2.39 sur Debian Lenny)

Aryeh Leib Taurog
la source
20

Il existe des solutions non mentionnées ici.

  1. Vous pouvez désactiver le hachage avec set +houset +o hashall

    help set dit:

    -h - Rappelez-vous l'emplacement des commandes au fur et à mesure de leur exécution. C'est activé par défault.

    hashall - Identique à -h

    set -h # enable hashing
    shopt -u checkhash # disable command existence check
    hash -p /some/nonexisting/dir/date date # bind date with /some/nonexisting/dir/date
    date # bash: /some/nonexisting/dir/date: No such file or directory
    set +h
    date # normal date output
    
  2. Vous pouvez vérifier qu’une commande trouvée dans la table de hachage existe avant de tenter de l’exécuter avec shopt -s checkhash

    help shopt dit:

    checkhash - s'il est défini, bash vérifie qu'une commande trouvée dans la table de hachage existe avant d'essayer de l'exécuter. Si une commande hachée n'existe plus, une recherche de chemin normal est effectuée.

    set -h # enable hashing
    shopt -u checkhash # disable command existence check
    hash -p /some/nonexisting/dir/date date # bind date with /some/nonexisting/dir/date
    hash -t date # prints /some/nonexisting/dir/date
    date # bash: /some/nonexisting/dir/date: No such file or directory
    shopt -s checkhash # enable command existence check
    date # normal date output
    hash -t date # prints /bin/date
    
  3. Vous pouvez lier NAME avec PATH avec hash -p PATH NAMEou BASH_CMDS[NAME]=PATH:

    shopt -u checkhash # disable command existence check
    hash -p /some/nonexisting/dir/date date
    date # bash: /some/nonexisting/dir/date: No such file or directory
    BASH_CMDS[date]=/bin/date
    date # normal date output
    
  4. Magie: PATH="$PATH"effectuehash -r

    De variables.c:

    /* What to do just after the PATH variable has changed. */
    void
    sv_path (name)
        char *name;
    {
        /* hash -r */
        phash_flush ();
    }
    

    Essayer:

    set -h
    hash -r
    date
    hash # prints 1 /bin/date
    PATH="$PATH"
    hash # prints hash: hash table empty
    
Evgeny Vereshchagin
la source
1
Je n'ai jamais compris pourquoi tout le mécanisme supplémentaire est fourni lorsque PATH = $ PATH fonctionne correctement. Si la variable PATH change, le cache de recherche PATH doit être invalidé. Logique.
jrw32982
Le cas d'utilisation qui n'est pas géré en invalidant le cache lorsque le PATH change est lorsque les emplacements des exécutables sont modifiés. Cela peut être courant lorsque vous utilisez le shell pour ajouter ou supprimer des programmes, uniquement pour le mettre en cache le dernier endroit où il les a trouvés.
Adam
Jouer avec la table de hachage de commande est un moyen formidable de vraiment dérouter quelqu'un qui essaie de déboguer un script bash.
Erik Aronesty
4

Comme l'utilisateur johntex l' a noté dans un commentaire à la réponse de l'utilisateur Tobu , l'action la plus simple dans Bash consiste à réorganiser uniquement votre programme:

hash svnsync

C'est tout.

Acumenus
la source