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

Dan*_*ien 319 bash cache executable

当我在没有指定可执行文件的完整路径的情况下执行程序时,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
Run Code Online (Sandbox Code Playgroud)

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

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

Tob*_*obu 406

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

$ type svnsync
svnsync is hashed (/usr/local/bin/svnsync)
Run Code Online (Sandbox Code Playgroud)

要清除整个缓存:

$ hash -r
Run Code Online (Sandbox Code Playgroud)

或者只有一个条目:

$ hash -d svnsync
Run Code Online (Sandbox Code Playgroud)

如需更多信息,请咨询help hashman bash

  • @Daniel 值得补充的是,在 bash 中,您可以使用命令“type _command_”来找出它是什么类型的命令 - 如果您的命令是散列的,“type”会告诉您。判断某些东西是 shell 内置还是别名也很有用。 (18认同)
  • 仅供参考,如果运行`csh`,要更改缓存的PATH,命令是`rehash`。 (4认同)
  • 在一个命令中,可以通过 `hash svnsync` 调用选择性重新散列。 (4认同)
  • 我很好奇,知道如何从脚本内部以影响父 shell 的方式执行此操作吗?答案中的方法均不适用于此用例。 (2认同)

Evg*_*gin 31

有这里没有提到的解决方案。

  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
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)
  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 ();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    尝试:

    set -h
    hash -r
    date
    hash # prints 1 /bin/date
    PATH="$PATH"
    hash # prints hash: hash table empty
    
    Run Code Online (Sandbox Code Playgroud)

  • 我一直不明白为什么当 PATH=$PATH 工作正常时提供所有额外的机制。如果 PATH 更改,则 PATH 查找缓存应该无效。说得通。 (3认同)

Ary*_*rog 29

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

hash -d svnsync
Run Code Online (Sandbox Code Playgroud)

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


Asc*_*ius 7

正如用户johntex在对用户Tobu回答的评论中指出的那样,Bash 中最简单的实际操作是仅重新散列您的程序:

hash svnsync
Run Code Online (Sandbox Code Playgroud)

就这样。