萧十一入职公司2年有余,便成为了一位很热心的实习生导师,新来的实习生与其说他是幸运的,不如说他是“幸运牌方便面“的,每次总被一个问题搞到深夜,饭也来不及吃,只能以面充鸡。
偶有遇到问题求教十一导师,十一导师语重心长且耐心地说:
“重八呀,这个问题嘛,你可以在浏览器输入三达不溜点摆渡点卡姆,一回车,再输入你的问题,搞腚!“
朱重八小实习生只能无语凝噎。。。。。。
天渐渐暗了下来,萧十一看着眼前的这个实习生,不由得心生感慨。用他那呆滞的眼神看着窗外,此时不由得想起他自己实习的那天。。。。。。
那天,是他来公司第100天,坐着585路公交车,半路上公交还抛锚着火了,着实有点不顺。换车之后,他就在想一个绕不开的终身的大事,运维到底是干什么的?能不能干一辈子?网上充斥着五花八门的,让人意乱情迷啊的答案。搜了一段时间实在顶不住早起的困意,依偎在玻璃窗边睡着了。梦里他梦到领导让他周末不用来加班了,回去休息休息。。。。
叮铃铃。。。。。。还没到公司,他就收到领导的紧急电话。
“喂,十一,你咋又迟到,快点,线上服务器挂了,抓紧时间!“
“喂,领导,公交车抛锚了,我马上就到。“,另外一个运维老兵今天刚好结婚请假,对十一来说是莫大的双重打击啊。
不由分说,萧十一急匆匆挂了电话,三步并作两步,赶到工位,打开电脑,查看监控,果然。有一批机器磁盘飙红。
“一定是磁盘空间满了!!!“
萧十一三下五除二,写了一个批量脚本检测了下,正如所料,有个服务的日志没做轮询,磁盘给撑爆了。
“咋整?“,十一心里暗想。
“rm -rf 吧,先救急!“
他们的项目其实并不大,十万的用户量,那时候的运维审批流程也没那么严格,再加上领导让救急,急火攻心,说干就干。
快速写了一个批量删除脚本,一把跑完,命令没报错,十几台机器运行完没报错,真是漂亮,自我窃喜。
可是,一查监控,磁盘指标还是飙红。于是又跑了一遍批量脚本检测了下,我乖,空间并没减少,咋回事?
按照之前他的导师给他的心路大法,就去摆渡了下,果然有这问题,太棒了!
页面赫然写着:
文件被其他程序或进程占用。即使文件被删除,如果其仍被其他进程或程序占用,则磁盘空间将无法释放。可以通过终端命令“lsof | grep deleted”查找所有被删除但仍被占用的文件,并杀掉该进程或关闭该程序来释放该文件占用的磁盘空间。
果然一试上述方法真的解决了。
这件事过后,萧十一心想,作为一名读过研的人,那就得有刨根问底精神,rm -rf删除的是什么,为什么删除了还能被进程占用?lsof是个什么高级玩意?带着问题,他就像写论文做实验一样,开始兴奋滴深究起来。
1. rm -rf删除的是什么?
通过对源码分析https://github.com/coreutils/coreutils/blob/master/src/rm.c,我们也能略知一二。
在rm.c源文件中包含了main函数,这个文件主要干了这么几件事:
a. 主函数使用getopt来处理rm命令行传入的参数。主要的选项包括:
如果没有提供要删除的文件名,会检查并报missing operand错误。
如果使用了--preserve-root选项,会设置一些变量比如x.root_dev_ino。
统计传入的要删除的文件名数量。
如果使用了-i选项,在删除多文件前会提示用户确认。
主要逻辑在rm()函数中,调用它来删除文件。
检查rm()的返回状态,并相应地以成功或失败退出程序。
b. rm()函数它有两个参数:
c. rm_fts函数
d. excise函数
e.unlinkat函数
根据unlinkat文档介绍:
unlink() deletes a name from the filesystem. If that name was the last link to a file and no processes have the file open, the file is deleted and the space it was using is made available for reuse.If the name was the last link to a file but any processes still have the file open, the file will remain in existence until the last file descriptor referring to it is closed.If the name referred to a symbolic link, the link is removed.If the name referred to a socket, FIFO, or device, the name for it is removed but processes which have the object open may continue to use it.
翻译如下:Unlink()会从文件系统中删除一个文件名称。如果该文件名称是指向某个文件的最后一个链接,并且没有进程打开该文件,那么该文件将被删除,它所使用的空间将可供重用。如果该文件名称是指向某个文件的最后一个链接,但仍有进程打开该文件,那么该文件将一直存在,直到关闭最后一个引用该文件的文件描述符。如果该名称引用了一个符号链接,则该链接将被删除。如果该名称引用了一个套接字、 FIFO 或设备,则该名称将被删除,但已打开该对象。
所以到这里就真相大白了,如果还想继续深入探究,还可以具体看下unlink函数的实现过程。
2. lsof是什么?
#!/bin/bash
# 检查参数数量
if [ $# -ne 1 ]; then
echo "用法: $0 <目标文件夹路径>"
exit 1
fi
# 获取目标文件夹路径
target_folder=$1
# 使用find命令查找目标文件夹下的所有进程占用的文件
find_result=$(find "$target_folder" -type f)
# 循环遍历每个找到的文件
while read -r file; do
# 使用fuser命令查找占用该文件的进程
pid=$(fuser "$file" 2>/dev/null)
# 如果找到了占用进程,则输出相应信息
if [ -n "$pid" ]; then
echo "文件 $file 被进程 $pid 占用"
fi
done <<< "$find_result"
执行结果参考如下:
[root@VM-1210-18-xxx xxxx]# sh fake_lsof.sh .
文件 ./fake_lsof.sh 被进程 3657653 占用
一番探究之后,萧十一欣喜若狂,如鱼得水。不禁感叹道,”做技术其实就是做学问啊!“
“老师你说的啥?”,实习生一听,不禁问道。
“路漫漫其修远兮,吾将上下而求索。”
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。