df 满了、du 却查不出来:一次云服务器磁盘“幽灵占用”排查实录
df 满了、du 却查不出来:一次云服务器磁盘“幽灵占用”排查实录
上周收到云监控告警:云服务器根分区使用率 97%。登录上去一看,df -h 显示 / 只剩几百 MB;可 du -sh /* 一路加下来,所有目录总量只有磁盘的一半。空间被谁吃了?
结论先行:最常见的真凶,是“已经被删除、但还被进程拿着”的文件——日志被 rm 删了,写日志的进程没重启,空间就不释放,而且 du 还查不出来。下面是完整排查链路,命令都可直接复用。
一、先对齐口径:df 和 du 本来就不是一回事
df读的是文件系统元数据:已分配出去的块有多少。du是遍历目录树逐个文件累加大小。
一个看“账面分配”,一个看“目录里能见到的”。两者有差值,差值本身就是线索——说明有分配了块、但在目录树里不可见的东西。
二、先排除三个经典坑
动手抓“幽灵”之前,先花一分钟排除:
df -i # 1. inode 是否用尽:小文件太多时,df 显示有空间也写不进去
mount | grep ' / ' # 2. 挂载点被遮挡:文件先写在挂载点目录下,之后又挂载了别的盘,du 就看不见了
du -x -d1 -h / 2>/dev/null | sort -hr | head # 3. du 加 -x:不跨文件系统,避免把别的分区算进来
这三项都没问题,差值还在,那就进下一步。
三、抓真凶:lsof 找 deleted
lsof +L1
# 或者
lsof | grep deleted
原理一句话:Linux 下 rm 只是删除目录项,只要还有进程开着这个文件的 fd,inode 引用计数就不为 0,数据块不会释放。du 遍历目录树看不到它,df 看块分配能看到——这就是“幽灵占用”。
实锤验证:
ls -lh /proc/<pid>/fd | grep deleted
能在 /proc/<pid>/fd 里看到标记为 (deleted) 的句柄,把它的大小和 df/du 的差值一对,对上就是它了。最常见的就是被 rm 掉、但进程没重载的应用日志。
四、修复:先优雅,再粗暴
按推荐顺序来:
- 让进程自己释放:很多服务收到
USR1会重开日志文件——kill -USR1 <pid>;或systemctl reload <服务>。 - 截断句柄(高危,先确认再执行):
: > /proc/<pid>/fd/N,空间立即释放,不用重启进程。 - 重启对应服务:上面的都不行再用。
不推荐直接 kill -9 生产进程,更不要指望“重启机器自动好”——不先找到是谁在写,重启后日志照写,几天后照样满。处理完再跑一遍 df -h,使用率会立刻回落。
五、别让它再发生
- 日志轮转用 logrotate 的
copytruncate,或在应用侧配好按天/按大小轮转; - 磁盘告警阈值设在 80% 而不是 95%,给排查留时间;
- 巡检脚本里加一行
lsof +L1,发现 deleted 大文件直接告警; - 这套分支我顺手做进了参赛作品《云排障智能体》的问诊决策树:症状选“磁盘空间不足”→回答几个问题→直接指向 deleted 句柄排查,把一次人工排查沉淀成了可复用的诊断路径。
六、三板斧(收藏版)
df -h && df -i
du -x -d1 -h / 2>/dev/null | sort -hr | head
lsof +L1
三条命令,覆盖了 90% 的“磁盘满了”现场。df/du 对不上,先想 deleted;deleted 没有,再回头查 inode 和挂载遮挡。按这个顺序走,基本不会走弯路。
- 点赞
- 收藏
- 关注作者
评论(0)