一个由硬链接引发的问题
一个由硬链接引发的问题
问题背景
最近关于 Fastjson 的漏洞又被爆出来了,作为修理工(哦不,专业的软件工程师),又到了我们表演的时候了。
文章图片
我们有很多服务是用的老版本的有漏洞的jar包,为了解决这个漏洞问题,我们决定来个偷梁换柱,使用新版本的jar包直接把老版本的有漏洞的jar版本直接覆盖掉。哎哎哎,要想程序搞得好,三十六计不可少。
问题现象
既然方案确定了,那就开始干,具体思路如下:
- 从环境上找出老版本的jar包,然后备份到一个备份路径下,这里备份是为了支持回退的功能。
- 然后把新版本的jar包拷贝到老版本jar包的路径下。
- 重启所有的微服务是jar包生效。
for 老版本的jar包 in 所有老版本的jar包;
do
备份老版本的jar包
将新版本的jar包拷贝覆盖老版本的jar包
done
整体思路很简单,但是问题就出在这个备份上面。在实际的测试过程中,发现备份的目录下,jar包的版本大多数都变成新版本的jar包了,而不是老版本的jar包,如下图所示,在
/tmp/home/testuser
下的 fastjson-1.2.70.jar
这个包的 Hash 值实际上和 fastjson-1.2.83.jar
这个包的 Hash 值一样。文章图片
文章图片
最开始一直以为是自己代码逻辑写的有问题,于是一遍一遍的检查。我先把新版本的jar包覆盖老版本的 jar 包这个逻辑去掉,然后计算备份路径下所有的 Hash 值,发现都是老版本的 jar 包,是没有问题的。
但是一旦我把覆盖老版本的 jar 包逻辑加上去,这个备份的 jar 包版本就变了,我反反复复搞了好几次结果都是一样的,真是让我百思不得其解。困扰程序员的两大难题之一在我脑海中产生了,它为啥就跑不起来呢?
文章图片
既然看不出来,那就只能使用程序员的必杀器了,Debug 一把。我把每次循环执行覆盖操作后,备份目录的下的 jar 的 Hash 值都算了一下,结果发现在执行第二次循环的时候,备份目录的下的 jar 文件就已经变成了新版本的jar包文件了。
观察到这个现象之后,我就开始思考为啥会出现这种情况呢?第二个循环的逻辑明明和第一次的逻辑是一样的,为啥结果就变了呢?
文章图片
当天搞了很久也没有找到原因是啥,脑壳都给我搞昏了。没办法,明天接着搞。第二天早上来,由于经过了一晚上的回血,思路又清晰起来了,觉得自己又行了。
文章图片
这个时候我想起来,之前有人好像给我说过,我们的jar包是做的硬链接的。这个让我想到了一个经典的面试题:Linux 的软链接和硬链接的区别是啥?区别是啥来着?嗯嗯……,想不起来了,书到用时方恨少啊,默默的流下了没有知识的泪水。
网上找了一些文章来看,又从电脑屏幕下把压着的《鸟哥的 Linux 私房菜》取出来复习一下。
然后登录到环境上,看了一下环境上老版本的 jar 包,发现确实是做的硬链接。为了演示这个情况,我在我自己的环境上复现了一下这种情况,如下图所示:
软链接和硬链接的区别可以参考网上的资料和书籍,我在这里就不细讲了。针对我当前遇到的这个问题,可以打个不恰当的比喻:硬链接就好像你照镜子一样,你做了什么样的改变,镜子里面的你也会做同样的改变。如上图所示,当我们改变
/home/testuser
目录下的 fastjson-1.2.70.jar
这个文件的内容时,/home/admin
目录下的 fastjson-1.2.70.jar
文件的内容会变得和它一样。知道了这个特性,我们再结合代码来分析一下:
- 已知条件:环境上有两个jar包文件:
/home/testuser/fastjson-1.2.70.jar
和/home/admin/fastjson-1.2.70.jar
这两个jar包是硬链接关系 - 推导:当我们执行第一次for循环到将新版本的jar包拷贝覆盖老版本的jar包这个步骤时,会把其中一个路径下的jar包版本替换成新版本的jar包了,这个时候相当于
/home/testuser/fastjson-1.2.70.jar
和/home/admin/fastjson-1.2.70.jar
这两个jar包都已经变成新版本的jar包了;当第二次for循环到备份老版本的jar包时,这个时候备份的是实际上已经是新版本的jar包了。这个就是为啥第二次以后备份的jar包版本都是新版本的原因了。
for 老版本的jar包 in 所有老版本的jar包;
do
备份老版本的jar包
将新版本的jar包拷贝覆盖老版本的jar包
done
解决方法
知道原因了,我们就思考上面的代码应该怎么改?很显然,备份和拷贝覆盖老版本的jar包这两个动作应该拆分到两个for循环中去实现才行,这样的备份这个for循环里面就会备份的是所有老版本的jar包。如下面的代码所示:
for 老版本的jar包 in 所有老版本的jar包;
do
备份老版本的jar包
done
for 老版本的jar包 in 所有老版本的jar包;
do
将新版本的jar包拷贝覆盖老版本的jar包
done
这个问题的解决主要是要理解硬链接的原理。说实话这个知识之前也看过很多遍,每次看的时候都觉得自己懂了,但是真正遇到问题的时候,才发现自己根本就没有懂。
通过这次问题的解决,我想我应该是对硬链接有了一定的了解。其实在日常的工作中,很多的小问题背后其实都对应的一些知识点的,如果我们能够把这些小问题搞清楚,其实对我们真正理解和掌握这个知识是有很大帮助的。好了,今天就到这里了,朋友们,我们下期再见!
【一个由硬链接引发的问题】
推荐阅读
- 《Java入门100练》|【第26天】给定 n 个元素的升序数组nums,求实现一个函数在nums中寻找target的下标 | 初识二分查找
- 《Java入门100练》|【第25天】给定一个长度为 n 的数组,统计每个数出现的次数 | 计数哈希
- 《Java入门100练》|【第24天】给定一个长度为 n 的数组,将元素 X 插入数组指定的位置 | 数组插入操作
- 力扣之有效的回文
- 投稿|大厂入局高考志愿填报,700元买一个锦绣前程?
- Node.js的路由、EJS模板引擎、GET和POST请求讲解
- 投稿|嘴硬,车企的传统艺能
- 力扣之斐波那契数列
- Vue3+TS+Vite+NaiveUI搭建一个项目骨架实现
- 一个快速切换一个底层实现的思路分享