如何清除Bash可执行文件路径的缓存?


256

当我在不指定可执行文件的完整路径的情况下执行程序时,Bash必须在其中搜索目录$PATH以查找二进制文件,看来Bash会在某种高速缓存中记住该路径。例如,我安装了一个Subversion从源代码到的构建/usr/local,然后svnsync help在Bash提示符下键入。Bash找到了/usr/local/bin/svnsync“ svnsync” 的二进制文件并执行了它。然后,当我删除Subversion的安装/usr/local并重新运行时svnsync help,Bash会响应:

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

但是,当我启动Bash的新实例时,它会发现并执行/usr/bin/svnsync

如何清除可执行文件路径的缓存?


7
有史以来最愚蠢的功能
Romeno

Answers:


322

bash确实缓存了命令的完整路径。您可以验证您尝试执行的命令是否已使用以下type命令散列:

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

要清除整个缓存:

$ hash -r

或者只是一个条目:

$ hash -d svnsync

有关更多信息,请参阅help hashman bash


15
@Daniel值得补充的是,在bash中,您可以使用命令“ type command ”来查找命令的类型-如果您的命令是散列的,“ type”将告诉您。告诉某些内容是内置的Shell还是别名也很有用。
Lunchmeat317

4
作为FYI,若要更改缓存的PATH(如果正在运行)csh,则命令为rehash
kurtm

上面的rehash命令也适用于zsh
尼尔·特拉夫特

对于一个更完整的答案见unix.stackexchange.com/questions/86012/...
扬FILIPPIDIS

4
在一个命令中,可以通过调用选择性重新哈希hash svnsync
Ioannis Filippidis 2014年

25

要只清除一个条目,您需要一个不同的标志:

hash -d svnsync

-r标志不带参数,并且将始终删除整个缓存。
(至少在Debian Lenny的bash 3.2.39中)


20

这里没有提到解决方案。

  1. 您可以使用set +h或禁用哈希set +o hashall

    help set 说:

    -h-在查找要执行的命令时记住其位置。默认情况下启用。

    hashall-与-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. 您可以先尝试检查哈希表中是否存在命令,然后再尝试执行该命令 shopt -s checkhash

    help shopt 说:

    checkhash-如果设置,bash在尝试执行之前检查在哈希表中找到的命令是否存在。如果哈希命令不再存在,则执行常规路径搜索。

    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. 您可以使用hash -p PATH NAME或将NAME与PATH绑定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. 魔术:PATH="$PATH"表演hash -r

    来自variables.c

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

    尝试:

    set -h
    hash -r
    date
    hash # prints 1 /bin/date
    PATH="$PATH"
    hash # prints hash: hash table empty

1
我从来不明白为什么当PATH = $ PATH正常工作时会提供所有额外的机制。如果PATH更改,则PATH查找缓存应无效。说得通。
jrw32982 '16

当PATH更改时,不能通过使高速缓存无效来处理的用例是可执行文件的位置更改时。当您使用外壳程序添加或删除程序时,仅使它缓存找到程序的最后位置时,这种情况很常见。
亚当

弄乱命令哈希表是一种真正使尝试调试bash脚本的人感到困惑的绝妙方法。
Erik Aronesty '18

4

正如用户johntexTobu用户的答案注释中指出的那样,Bash中最简单的实际操作是重新哈希程序:

hash svnsync

就这样。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.