/proc/PID/fd/N 清空释放;预防需配置 logrotate 或应用内日志轮转。 确认是不是真没释放:df 和 du 对不上 执行 df -h 看磁盘使用..."/>

Linux 文件删除后空间未释放的排查

13次阅读

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

Linux 文件删除后空间未释放的排查

确认是不是真没释放: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 清内容

选哪个,取决于你能不能停服务:

  • 能停:直接 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 ——漏掉一个,空间就卡住一块。

text=ZqhQzanResources