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

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


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

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

评论

有史以来最愚蠢的功能
bash缓存车祸?

@Romeno该功能非常好(重新运行命令可以节省时间),这是愚蠢的实现。 Bash应该自动删除不再存在可执行文件的哈希。

#1 楼

bash确实缓存了命令的完整路径。您可以验证使用type命令对要执行的命令进行哈希处理:

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


要清除整个缓存,请执行以下操作:

$ hash -r


或仅一个条目:

$ hash -d svnsync


有关其他信息,请参阅help hashman bash

评论


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

–午餐
2011年5月11日在20:59

作为一个仅供参考,如果要运行csh来更改缓存的PATH,请重新哈希该命令。

–kurtm
13-10-12在0:21

上面的rehash命令也适用于zsh。

–尼尔·特拉夫(Neil Traft)
13年10月10日在21:35

在一个命令中,可以通过哈希svnsync调用选择性重新哈希。

–艾奥尼斯·菲利皮迪斯(Ioannis Filippidis)
14年8月9日,0:44

我发现我正在运行破折号而不是bash-因为破折号哈希-d不起作用;哈希svnsync都适用。

– Iiridayn
16 Jul 19'0:10



#2 楼

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

hash -d svnsync


-r标志没有参数,并且将始终删除整个缓存。

#3 楼

有此处未提及的解决方案。



您可以使用set +hset +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



在尝试使用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



您可以将NAME与PATH绑定在一起,并带有hash -p PATH NAMEBASH_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



魔术: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




评论


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

– jrw32982
16年7月27日在19:48

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

–亚当
17年12月7日在21:31

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

– Erik Aronesty
18年1月29日在18:12



#4 楼

正如用户johntex在对Tobu用户的回答的评论中指出的那样,Bash中最简单的实际操作是仅对您的程序进行哈希处理:

hash svnsync


就这么简单。