DEBUG.WIKI
丽萨主机;为跨境业务选好 IP;原生 / 住宅 IP · 按套餐选择;查看 IP →
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Bash 总是执行已删除的旧路径:清除当前 shell 命令缓存

工具迁移后 Bash 仍执行已删除的旧路径时,检查同一 shell 的 hash 记录和 PATH,定点或整体清除缓存,再排除别名、函数及加载器错误。

把一个工具从 /usr/local/bin 移到 /usr/bin 后,完整新路径能运行,直接输入命令名却仍报旧路径的 No such file or directory。新开 Bash 会正常,只有原来的终端继续找旧位置时,应检查这个 shell 的命令路径缓存。

Bash 会记住从 PATH 找到的外部命令位置。磁盘上的旧安装被删除,不一定立即清除已有 shell 的记录。这条处理针对 Bash;zsh、csh 及其他 shell 的命令和缓存规则需另行核对。

在出错的同一个 Bash 中检查

下面用 example-tool 表示真实命令名,不运行它的业务操作:

type example-tool
hash -t example-tool
type -a -p example-tool

第一条查看命令会如何解释,可发现别名、函数或被记住的路径。第二条只看该命令当前是否已有 hash 记录;没有记录时会返回非零,不能据此认定磁盘上没有安装。

type -a -p 搜索 PATH 中的可执行文件位置,不查询该 hash 表。若记录指向已删除的旧文件,而这次搜索找到可信的新安装,便符合缓存失效的处理条件。应在实际失败的终端里检查;另一终端、脚本或 sudo 启动的 shell 有自己的执行环境。

不要只靠外部 which 的结果判断当前 Bash 一定会执行同一路径。它与 Bash 对别名、函数及缓存的解释可能不同。工具有多个安装位置时,还需确认 PATH 的顺序和想采用的版本,不能只选第一个看起来存在的文件。

只忘记对应命令,或清除全部记录

确认新位置正确后,在当前 Bash 内执行:

hash -d example-tool

这会删除该命令的缓存项,下一次按命令名查找时重新搜索 PATH。若刚迁移了多个工具,可以使用:

hash -r

-r 清除全部已记住的位置,不接一个命令名来表示定点清除。两种方式按实际范围选用,无需都执行。它们不删除程序、不安装依赖,也不修改 PATH 的内容。

把这些命令放在新启动的脚本中执行,只会作用于那个脚本使用的 shell,不能替父终端清除缓存。需要修复交互终端,就在该终端中调用 Bash 内置命令。没有必要重启服务器或重新安装整个工具链。

别名、函数和缺失解释器走另一条路径

如果 type 显示的是别名或函数,应检查它是否写死了旧位置,再按原配置来源修改。hash -r 不会删除别名或改变函数定义。

清除后仍找不到命令,就重新核对 PATH 和实际安装文件。新路径也不能执行时,继续检查文件权限、脚本首行解释器或 ELF 加载器;存在一个文件却报不存在,可能指向它依赖的解释器或加载器,而不是 hash 缓存。不要为查找问题创建一个指向未知版本的全局软链接来掩盖。

Bash 另有 checkhash 选项,在准备执行已缓存命令时确认路径仍存在,不存在则重新搜索。但它不会发现“旧文件还在,另一个更优先的新版本刚被安装”的所有变化,不能代替明确管理版本及 PATH。需要采用这项行为时,先评估脚本或终端初始化设置,不必为一次失效记录永久关闭缓存。

确认调用的是预期版本

清除后再次查看 type 的结果,并用该工具支持的无副作用版本查询或原来的受控检查入口确认实际版本。错误消失,却执行了 PATH 后面另一份旧安装,不算完成迁移。

hash 的修改只影响当前 shell 的记录,其他长期运行的终端仍需各自处理。自动任务还要核对自身的 PATH 和启动方式,不把手动终端恢复当成所有入口已更新。

如果只是清除缓存,无需恢复磁盘文件。迁移本身要回退时,按安装方式恢复旧版本与相应 PATH,随后刷新当前 shell 的记录;无法通过“恢复一个缓存字符串”重建已经删掉的程序。修改别名、启动配置或安装位置前,应分别保存原设置,避免同时变更多层造成新的调用混乱。