df 显示 100%,但 du 加起来只有一半——这种「账对不上」的情况,多半是被删掉却仍被进程占用的文件。本文按排查顺序整理一套固定动作。
第一步:确认是哪块盘
df -hT # 带文件系统类型,看 Use% 那一列
df -i # 如果这里满了,那是 inode 而不是容量df -i 经常被忽略。小文件极多时(比如缓存目录塞满了几十万个碎片文件),容量还剩很多但 inode 已经耗尽,新文件一律创建失败。
第二步:找出大目录
du 从根目录扫会非常慢,建议逐层下钻:
# 只看当前层,按大小排序,别加 -sh 那样会把子目录合并掉
du -h --max-depth=1 / | sort -rh | head -20锁定最大的目录后,进入它重复上一条命令,通常三四层就能定位到元凶。
第三步:处理「已删除但被占用」的文件
如果 du 和 df 差距很大,用 lsof 找被删但仍被打开的文件:
lsof -nP | grep deleted | sort -k7 -rn | head -20典型输出是一堆日志文件。这些空间只有等持有它的进程退出才会真正释放。不要去 kill -9,正确做法是通知对应进程重新打开日志:
# Nginx:直接发信号即可,不会中断连接
nginx -s reopen
# 或者用 logrotate 手动跑一次
logrotate -f /etc/logrotate.d/nginx第四步:确认释放结果
df -h / # 空间应当立刻回落顺手加一个告警
与其等它满了再救火,不如让脚本提前说话:
#!/bin/bash
THRESHOLD=85
USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$USAGE" -ge "$THRESHOLD" ]; then
echo "磁盘使用率 ${USAGE}%,请检查" | mail -s "磁盘告警" ops@example.com
fi配合 crontab 每小时跑一次,基本就不会再遇到半夜磁盘写满的事了。
小结
固定顺序:df -hT → df -i → du --max-depth=1 逐层下钻 → lsof | grep deleted。前三步解决 90% 的问题,第四步解决剩下那 10% 里最迷惑人的一类。