Linux 磁盘空间爆满排查实战
一、问题背景
磁盘空间不足是服务器最常见的运维故障之一。典型现象是 df -h 显示磁盘已用 100%,应用开始报 No space left on device,但用 du 逐目录查看时却找不到明显的大文件——“空间神秘消失”的情况往往最让人头疼。
本文整理了磁盘空间排查的完整思路,以及几个最经典的”隐藏空间”坑点。
二、基础排查
1. 确认磁盘占用情况
1 | df -h |
- 定位是哪个挂载点已满
- 关注
Use%列和Mounted on列
2. 逐层定位大目录
1 | du -h --max-depth=1 -x / | sort -rh | head -20 |
-x表示不跨文件系统,避免统计到其他挂载点的内容- 从根目录逐层下钻,直到找到占用最大的目录
| 命令 | 作用 |
|---|---|
df -h |
查看磁盘整体使用率 |
df -i |
查看 inode 使用率 |
du -sh <目录> |
统计指定目录总大小 |
find / -xdev -type f -size +1G |
查找大于 1G 的单个文件 |
三、坑一:inode 耗尽
现象:df -h 显示磁盘还有不少空间,但创建或写入文件时报 No space left on device。
原因:小文件数量达到了文件系统的 inode 上限,空间还有,但”名额”用完了。
排查:
1 | df -i |
IUse% 为 100% 即为 inode 耗尽。常见来源:
- 邮件队列
/var/spool/postfix/maildrop/(大量退信小文件) /tmp下残留的临时文件- 程序运行时产生的海量小缓存文件
解决:
1 | # 统计哪个目录下小文件最多 |
四、坑二:文件已删除但空间未释放
现象:du 统计出的所有文件大小加起来,远小于 df 显示的已用空间。
原因:某个进程仍持有已删除文件的句柄。rm 之后空间并不会释放,要等进程关闭该文件(或进程退出)才会真正回收。
排查:
1 | # 查找所有被删除但仍被进程占用的文件 |
解决:
1 | # 方式一:重启或结束对应进程(推荐,如日志服务) |
⚠️ 注意:不要对正在写入的日志文件直接
rm,同样的问题会再次出现,正确做法是cat /dev/null > <日志文件>或配置 logrotate。
五、坑三:systemd journal 日志
journald 默认会一直累积系统与服务的日志,是 /var 分区的隐藏空间大户。
排查:
1 | journalctl --disk-usage |
立即清理:
1 | # 按总量限制清理 |
永久限制:编辑 /etc/systemd/journald.conf:
1 | SystemMaxUse=200M |
生效:
1 | systemctl restart systemd-journald |
六、坑四:Docker 容器日志
Docker 容器日志(/var/lib/docker/containers/ 下的 *-json.log)也是磁盘空间大户,其限制配置与清理脚本参见之前的文章:Docker日志过大的解决方案。
七、其他容易被忽略的占用
| 位置 | 说明 |
|---|---|
/var/log/ |
历史日志未做轮转,或 logrotate 配置失效 |
/var/spool/postfix/ |
邮件队列堆积,同时吃磁盘和 inode |
| core dump 文件 | 程序崩溃产生的 core 文件,可用 find / -name "core.*" 查找 |
| 数据库日志 | MySQL binlog、undo log 等未及时清理 |
/tmp、/var/tmp |
临时文件未设置自动清理 |
八、最佳实践
- 监控告警:部署磁盘使用率监控(如 Zabbix、Prometheus + node_exporter),建议阈值 85% 告警。
- 日志轮转:检查并配置
/etc/logrotate.conf及/etc/logrotate.d/下的各服务配置。 - 限制日志上限:journald 配置
SystemMaxUse,Docker 配置max-size/max-file(见 第 58 篇)。 - 定期巡检:写一个巡检脚本(
df -h、df -i、journalctl --disk-usage)配合 crontab 定时执行并输出结果。
九、总结
磁盘排查遵循”先看 df,再挖 du,最后查 inode 和句柄“的思路:
| 现象 | 原因 | 关键命令 |
|---|---|---|
df 显示满但 du 对不上 |
已删文件仍被进程占用 | lsof | grep deleted |
| 有空间但写不进去 | inode 耗尽 | df -i |
| 日志越滚越大 | journald / Docker 未限制 | journalctl --disk-usage |
大部分”空间神秘消失”的问题都能用上面的方法定位,配合监控和日志限制可以避免再次发生。