bash命令缓存导致命令执行失败的问题
1、问题背景
为了修复老版本 vsftpd 的安全漏洞,需要把生产环境上 vsftpd 版本升级到 vsftpd-3.0.5,因为直接使用 rpm 包的方式进行升级还涉及到下层依赖包的升级(生产环境上的依赖包版本不能随意变更,可能会影响其他上层应用),所以打算采用源码编译的方式进行升级,在本地一个相同环境上基于vsftpd-3.0.5 源码编译出对应可执行二进制文件,再用该配置文件替换生产环境上老版本的可执行二进制文件。
2、问题现象
本地基于 vsftpd-3.0.5 源码编译出对应可执行二进制文件后,找了个环境进行测试,测试环境自带的老版本 vsftpd-2.2.2 的可执行二进制文件在 /usr/sbin/ 路径下,现在将它删掉,然后直接将本地编译好的新版本 vsftpd-3.0.5 的可执行二进制文件拷贝到 /usr/local/sbin/ (放的目录跟原来不一样,是因为实际生产环境上对应的文件在这个目录下),但是拷贝完之后,执行 vsftpd 命令查看版本发现命令执行不了,报错找不到对应的二进制文件,但是which是可以查看到该命令正确的二进制文件路径的,PATH环境变量里边也有该路径
3、问题原因
仔细看命令报错可以看到找vsftpd二进制文件时还是去 /usr/sbin/下去找到的,跟which查出来的不一致,很容易联想到是缓存问题导致执行命令时还去老的路径去查,但之前对这块也没有深入了解,所以学习一下。
bash会把历史执行过的命令对应二进制文件路径缓存下来,这样下次执行的时候就不需要再从PATH中指定的各个路径中查找了,大大加快了命令执行的效率,这个缓存可以通过以下几条命令来管理:
查看bash缓存中记录的命令及其二进制路径:hash -l
删除bash缓存中指定命令的记录:hash -d <command>
删除bash缓存中所有命令的记录:hash -r
正常情况下bash命令缓存当然是好的,但像这种可执行文件路径发生变化的场景,就会出现缓存未更新导致命令执行失败的问题。
通过 hash -l 命令可以验证,上边新版本的 vsftpd 二进制文件找不到就是因为之前执行vsftpd命令时已经缓存了其二进制文件路径 /usr/sbin/vsftpd ,因此升级后再次执行该命令时默认直接从缓存中记录的老路径查找二进制文件,当然找不到了
4、解决方案
针对上述这种问题,最快的解决方案就是直接使用 hash -d 手动删除对应命令的历史缓存,这时再执行对应命令,就可以找到新版本的二进制文件了, 再使用 hash -l 命令可以验证缓存中的命令路径已经更新,如上边 vsftpd 命令缓存删除后就可以正常执行了:
另一种方案就是退出当前会话,然后重新登录,内存中的命令缓存也会被自动刷新