答案是:先比对 df 与 du 差值是否显著(如 df 显示 97% 而 du 总和仅 82g),再用 sudo lsof +l1 精准定位 link count 为 0 的已删未释放文件,而非不可靠的 lsof | grep deleted;确认后优先发 sighup 或 reload 服务以安全释放空间。

因为文件虽被 rm 移除了目录项,但进程(如 nginx、java、dockerd)仍在往它的文件描述符里写数据——内核不会回收 inode 和数据块,直到所有 fd 关闭。
怎么确认是这个问题而不是其他原因
先比对 df 和 du 是否明显不一致:
- 运行
df -h /看整体使用率(比如显示 97%) - 再跑
du -sh /* 2>/dev/null | sort -h统计各目录真实占用(可能只加起来 82G) - 差值超过几百 MB,且集中在日志目录(如
/var/log),基本就是已删未释 - 排除 ext4 journal 延迟:等 1 分钟再
df,若没变化,就不是缓存问题;sync也无效
为什么 lsof | grep deleted 不可靠
它会误匹配路径含 deleted 字样的正常文件(比如 /tmp/deleted_cache/),漏掉真问题,也干扰判断。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 正确命令是
sudo lsof +L1:只抓 link count 为 0 的打开文件,即真正被unlink但 fd 活着的文件 - 加限定更快:
sudo lsof +L1 /var/log(查日志目录)、sudo lsof -u root +L1(查 root 用户) - 输出中重点看
PID、COMMAND、FD(如3w表示写入)、SIZE/OFF、最后一列带(deleted)
echo > /proc/PID/fd/FD 能立即释放,但有副作用
这条命令直接清空 fd 对应的文件内容,空间秒退,进程也不中断——但它会丢掉当前缓冲区里还没刷盘的日志。
- 适用场景:日志服务(如
rsyslog、logrotate配置不当)或临时应急 - 不适用场景:数据库写入中的事务日志、容器内应用 stdout/stderr 重定向到已删文件
- 验证是否生效:
ls -lh /proc/PID/fd/FD应显示大小归零;再df -h确认空间回落 - 更稳妥方式:发
SIGHUP(kill -HUP PID),让进程自己 close + reopen 日志文件,保留缓冲内容
真正难处理的是多进程共用同一个已删日志文件(比如多个 nginx worker),+L1 会列出一堆 PID,但 kill 其中一个未必清空全部 fd;此时得看服务是否支持平滑 reload(如 nginx -s reload),否则只能逐个确认 fd 归属再操作。










