
在 Linux 服务器上,磁盘空间排查有一套固定套路:先用 df 确认是空间满还是 inode 满,再用 du 逐层定位大目录,最后针对性清理。走完这三步,绝大多数「磁盘写满导致服务不可用」的问题都能在十分钟内定位到具体文件。
一、先用 df 判断真正的原因
1. df -h 与 df -i 看的不是一回事
df -h 展示块设备的空间占用,df -i 展示 inode 数量占用。两者都可能先满:空间满的报错是 No space left on device,而 inode 满时即使 df -h 显示还有几十 GB 空闲,创建任何新文件同样失败。
df -h # 查看各分区空间占用
df -i # 查看 inode 使用率
重点看 Use% 与 IUse% 两列。根分区写满最常见,/var、/home 单独分区也会各自满。若 Use% 正常而 IUse% 到 100%,直接去第二节找小文件。
2. inode 耗尽的典型场景
inode 在格式化时一次性分配,记录的是文件「有多少个」而非「有多大」,常见凶手有三类:
- 会话文件堆积:
/var/lib/php/sessions下几十万个sess_小文件 - 邮件队列:
/var/spool/postfix/maildrop的大量残件 - 缓存碎片:程序按天按秒写日志或缩略图,从不清除,日积月累数量惊人
find /var -xdev -type f | wc -l # 统计 /var 下的文件数量
-xdev 表示不跨文件系统,避免把挂载的其他分区一起数进来导致统计失真。
二、用 du 逐层定位大头
1. du --max-depth 排序法
确认空间满后从根目录逐层收窄。--max-depth=1 只统计当前层的直接子项,配合 sort -h 排序,能立刻看出谁在吃空间。
du -x --max-depth=1 -h / | sort -rh | head -15
# 锁定某个目录后继续下钻
du -x --max-depth=1 -h /var | sort -rh | head -15
-x 与 -xdev 作用相同,只统计同一文件系统。去掉 -x 会把挂载的日志盘、数据盘一并算进根目录,结论就错了。
2. 已删除但空间未释放的文件
这是最让人困惑的情况:du 统计出的总和远小于 df 报告的占用量。原因是文件被 rm 删除后仍有进程持有句柄,inode 与磁盘块都不会释放。用 lsof +L1 可列出这类文件,处理方式是重启持有它的进程;对可截断的日志,用 shell 重定向清空内容即可,不要直接强杀进程。
三、清理与预防
1. 日志是第一优先级
journalctl --disk-usage
journalctl --vacuum-size=200M # 只保留最近 200M 日志
对正在被写入的日志文件,用 truncate -s 0 xxx.log 清空,而不是 rm:rm 之后进程句柄仍指向旧 inode,空间并不会释放。
2. 包管理器缓存与临时文件
yum clean all # CentOS / RHEL
apt-get clean # Debian / Ubuntu
清理 /tmp 前先用 lsof +D /tmp 确认没有进程正在使用其中的文件,误删临时文件会直接打断正在运行的任务。
3. 三条必须遵守的注意点
- 清理前先确认文件归属,
/var/lib/mysql、/var/lib/docker下的目录绝不能当缓存删除。 df与du结果不一致时,优先用lsof +L1找未释放的句柄,不要盲目扩容。- 长期方案是给日志加 logrotate 策略并设置分区告警阈值(80%),比事后救火可靠。
关键配置提示
df -h看空间、df -i看 inode,两者之一满都会导致写失败du -x --max-depth=1 -h / | sort -rh是定位大目录最快的组合- 正在写入的日志用
truncate -s 0清空,不要用rm

快来评论,快来抢沙发吧~