Linux 云服务器磁盘占满排查实战:从 df、inode 到已删除未释放文件的四步流程
背景
云服务器上最常见的“半夜告警”之一就是磁盘满了:应用写日志失败、数据库无法落盘、连 ssh 登录后敲命令都变慢。很多人第一反应是删日志,但有时删完 df 依然显示 100%,或者空间明明有剩余却提示 No space left on device。本文整理一套我自己排查 Linux 云服务器磁盘占满的流程,按四步走:看容量、看 inode、找大文件、查已删除但未释放的文件。
一、先确认是哪个分区满了
不要凭感觉,先用 df 看各挂载点:
df -hT df -i
df -h 看容量,df -i 看 inode。两个命令都要看,因为报错信息一模一样,原因完全不同。常见的是根分区 / 满了,或者数据盘挂载点(例如 /data)满了。如果数据盘根本没出现在 df 里,说明没有挂载,应用其实写进了系统盘的同名目录,这也是系统盘莫名变满的常见原因,可以用 lsblk 和 cat /etc/fstab 核对。
二、容量满:逐层定位大目录
确定分区后,用 du 逐层下钻,-x 参数表示不跨文件系统,避免把其他挂载点算进来:
du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -10 du -xh --max-depth=1 /var 2>/dev/null | sort -rh | head -10
找到最大的目录后继续往下一层,通常几次就能定位。常见元凶有:
- /var/log 下没有轮转的应用日志或 journal 日志;
- /var/lib/docker 下的镜像、容器日志和无用的卷;
- /tmp 或业务目录里的临时文件、core dump;
- 数据库的 binlog、慢日志、备份文件。
如果想直接列出大文件,可以用:
find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null
三、inode 满:小文件太多
df -i 显示 IUse% 为 100% 时,说明小文件数量耗尽了 inode,哪怕容量只用了一半也无法创建新文件。统计各目录文件数:
for d in /var/* /tmp /home/*; do echo "$d $(find $d -xdev 2>/dev/null | wc -l)"; done | sort -k2 -n -r | head
常见来源是会话文件、邮件队列、缓存碎片文件。清理后要同时修复产生它们的源头,比如给会话目录加过期清理任务,否则过几天还会复发。
四、删了文件空间却没释放
这是最容易让人困惑的情形:rm 了几个十几 GB 的日志,df 数字纹丝不动。原因是文件虽然从目录里删除了,但仍有进程持有它的文件句柄,空间要等进程关闭文件才会释放。用下面命令查:
lsof +L1 | grep deleted lsof -nP | grep '(deleted)' | sort -k7 -n -r | head
输出里能看到持有文件的进程 PID 和文件大小。处理方式有两种:一是重启或重载该进程(例如 nginx -s reopen 或 systemctl restart),让它重新打开日志;二是不方便重启时,直接清空文件而不是删除它:
: > /proc/<PID>/fd/<FD>
以后清理日志时,也建议养成习惯:对仍在写入的日志用 truncate -s 0 文件名 清空,而不是 rm。
五、处理完之后的收尾
- 给日志配置 logrotate,设置按大小或按天切割、保留份数并压缩;
- Docker 场景在 daemon.json 里为 json-file 日志驱动配置 max-size 和 max-file;
- journald 通过 SystemMaxUse 限制总占用;
- 在云监控里为磁盘使用率配置告警,建议 80% 就提醒,而不是等到 95% 以上;
- 如果业务数据确实增长,评估扩容云硬盘,扩容后需要再执行 growpart 和 resize2fs(或 xfs_growfs)让文件系统识别新容量。
小结
磁盘满了不要急着乱删:先 df -h 与 df -i 判断是容量还是 inode,再用 du 下钻找大目录,最后别忘了用 lsof 检查已删除未释放的文件。清理之后补上日志轮转和监控告警,才能真正避免下一次半夜被叫醒。
- 点赞
- 收藏
- 关注作者
评论(0)