登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux ext4 文件删除后空间没有释放是什么原因

来源:17golang原创

时间:2026-09-07 13:04:55 468浏览 收藏

在 ext4 上执行 rm 删除大文件后,df -h 仍显示磁盘接近满,最常见的原因不是 ext4 “删除失败”,而是某个进程还持有这个文件的打开描述符。目录里的文件名已经消失,但 inode 和数据块要等最后一个打开引用释放后才真正回收。

先用 df 确认哪个挂载点紧张,再用 lsof +L1 找出已删除但仍打开的文件;确认服务可以安全重载或重启后,空间通常会立即回收。
要点速览
  • du 只统计目录树中还能访问到的文件,不能代表所有仍占用块的对象。
  • lsof +L1 重点查看链接数为 0 的打开文件,输出中的 (deleted) 是关键线索。
  • 生产环境优先平滑重载或重启对应服务,不要直接对陌生 PID 执行 kill -9。

一、为什么 rm 后 df 仍然不变

Linux 文件名只是目录项对 inode 的一个引用。执行 rm 后,目录项被移除,新的进程不能再通过原路径打开它;但已经打开文件的进程仍然拥有文件描述符,内核仍需保持对应的文件对象和数据块。

因此会出现一个很容易误判的差额:du -sh /var/log 看不到刚删除的日志,而 df -h /var 仍然显示大量空间被占用。真正的回收点不是删除命令返回的时刻,而是最后一个引用关闭的时刻。进程退出、主动关闭描述符或服务重启,都可能触发回收。

Linux ext4 删除文件后目录项 inode 文件描述符和进程的静态关系
图1:目录项消失后,仍被文件描述符引用的 inode 仍会占用 ext4 空间。

二、用 lsof 定位哪个进程还持有文件

排查时不要一上来扫描整个根目录。先找出紧张的文件系统,再限定挂载点,结果更容易解释,也不容易给线上机器增加无谓开销。

# 先确认哪个挂载点的可用空间异常
df -hT /var

# 对照目录树中仍可见的文件总量
du -xsh /var/log

# 只列出链接数小于 1、但仍被进程打开的文件
lsof -nP +L1 /var

重点看 COMMANDPIDFDSIZE/OFFNAME。如果名称末尾出现 (deleted),说明路径引用已断开;若文件很大,且所在设备与 df 检查的是同一个挂载点,就基本能解释“du 很小、df 仍满”的现象。

命令或字段观察对象排障用途
df -hT文件系统容量确认设备、类型和挂载点
du -xsh目录树可见文件排除普通大文件和跨挂载误算
lsof +L1进程持有的已删除文件定位 PID、FD 和占用大小
df du lsof加L1与Linux ext4挂载点和deleted文件的对应关系
图2:用 df、du、lsof 分别观察文件系统、目录树和进程引用,找出空间差额的来源。

三、生产环境怎样释放空间又不误杀服务

确认 PID 后,先查它属于哪个服务、是否正在写入以及是否有主备或滚动发布能力。正在写日志的进程不能只看“文件已删除”就强制结束,否则可能丢失请求、连接或未刷新的缓冲数据。

# 查看 PID 的命令行,避免只凭 COMMAND 列猜服务
ps -fp 2486

# 查看该服务当前的 systemd 状态和最近日志
systemctl status example-worker.service --no-pager
journalctl -u example-worker.service -n 30 --no-pager

# 确认变更窗口后,优先让服务按自己的关闭流程释放描述符
sudo systemctl restart example-worker.service

# 回到同一挂载点确认空间是否已经回收
df -hT /var

如果服务支持重新打开日志,可以先使用它的官方 reload 方式;只有在确认无平滑方案、且已完成流量切换或故障处置时,才考虑停止进程。直接操作 /proc/PID/fd/FD 属于高风险手段,除非你清楚应用的写入语义和恢复方式,否则不应作为通用教程步骤。

  • 服务仍在写入:先保存 PID、FD、文件大小和服务状态,安排重载或重启。
  • 多个进程持有同一类 deleted 文件:逐个确认归属,不要批量杀进程。
  • 重启后空间仍不变:重新执行 lsof +L1,确认是否还有其他 PID 或其他挂载点。

四、常见问题

为什么 lsof 没有输出,但 df 还是很满?

可能是查询路径与挂载点不一致、权限不足、文件已经真正关闭,或者空间问题并非 deleted 文件。分别去掉路径限制检查目标挂载点,并核对 inode、容器挂载和其他大文件。

删除后 du 和 df 的差额一定是打开文件吗?

不一定。还要考虑多个挂载点、预留空间、稀疏文件、容器 overlay 文件系统等情况。只有 lsof +L1 找到同一设备上的大文件,才能把它作为本次差额的直接证据。

可以直接 kill -9 解决吗?

不建议。SIGKILL 会跳过应用自己的清理逻辑,可能造成请求中断或数据损失。先确认服务身份和业务影响,再用平滑重载、正常重启或经过审批的停止操作释放文件句柄。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>