df 与 du 差值即“已删未释”空间;用 lsof +L1 找 deleted 文件;可 kill 进程或 echo "" > /proc/PID/fd/N 清空释放;预防需配置 logrotate 或应用内日志轮转。

确认是不是真没释放:df 和 du 对不上
执行 df -h 看磁盘使用率,再用 du -sh /* 2>/dev/null | sort -h 统计根下各目录真实大小。如果 df 显示用了 95%,但 du 加起来才 60%,差值大概率就是“已删未释”的空间。
注意:du 不会统计被进程占用的已删文件,所以它永远比 df 少;这个差值不是误差,是线索。
找谁在锁着已删文件:lsof + grep deleted
lsof 是唯一能看见“幽灵文件”的命令——那些路径显示为 /var/log/app.log (deleted) 的条目,就是罪魁祸首。
-
lsof +L1:只列标记为 deleted 的打开文件(推荐,快且准) -
lsof /var/log | grep deleted:限定路径查日志类场景 - 输出中关键列:
PID(进程号)、COMMAND(进程名)、FD(文件描述符,如3w)、最后一列(deleted)
别信 ls /var/log/app.log 找不到就以为完事了——只要进程还开着它,空间就钉死不放。
释放空间的两种实操选择:杀进程 or 清内容
选哪个,取决于你能不能停服务:
在原版的基础上做了一下修正评论没有提交正文的问题特价商品的调用连接问题去掉了一个后门补了SQL注入补了一个过滤漏洞浮动价不能删除的问题不能够搜索问题收藏时放入购物车时出错点放入购物车弹出2个窗口修正主题添加问题商家注册页导航连接问题销售排行不能显示更多问题热点商品不能显示更多问题增加了服务器探测 增加了空间使用查看 增加了在线文件编辑增加了后台管理里两处全选功能更新说明:后台的部分功能已经改过前台
- 能停:直接
kill -9或systemctl restart nginx。重启后内核自动回收所有句柄,最彻底。 - 不能停(比如生产环境 HTTP 服务):用
echo "" > /proc/清空文件内容。例如/fd/ echo "" > /proc/4399/fd/38,对应 nginx 写入 access.log 的那个 fd。操作后空间立刻释放,进程继续写日志,文件句柄不变。
⚠️ 别用 > /var/log/app.log ——这会创建新 inode,原已删文件的空间仍不释放;必须走 /proc/PID/fd/ 这条路。
预防比抢救重要:别让日志自己长成巨兽
这类问题 90% 出现在日志文件上。手动 rm 只是掩耳盗铃,根源在于没有轮转机制:
- 用
logrotate配置自动切割+压缩+过期删除,而不是靠人想起来去删 - 临时清空日志,优先用
truncate -s 0 /var/log/app.log或> /var/log/app.log(注意:仅适用于进程已关闭该文件或支持重打开) - 检查应用是否开启日志 rotate 功能(如 nginx 的
reopen、Java 应用的 logback rollover)
真正棘手的情况是多个进程共用一个已删文件(比如父子进程都打开过),这时单 kill 一个 PID 不够,得看 lsof 输出里所有相关 PID ——漏掉一个,空间就卡住一块。









