Linux 文件删了,df 为什么不降?用 /proc 和 lsof 找到占空间的 FD

举报
yd_237867988 发表于 2026/10/27 11:20:50 2026/10/27
【摘要】 用4 MiB临时文件实验解释:删除路径后,打开的文件描述符为何仍可读取。结合 lsof 与 /proc 定位持有者,说明正常释放空间的方法,以及盲目强杀或截断文件的风险。

执行 rm 后,目录里看不到大文件,df -h 的使用量却没变化,常见原因是:文件名已经解除链接,但某个进程仍持有该文件的打开文件描述符(FD)。目录项负责让路径找到文件;进程的 FD 则是内核对打开对象的引用。删除最后一个目录链接,不会强行让已有 FD 失效,数据块通常要等最后一个引用关闭后才可回收。因此 ls 看不到它,df 仍会计入块占用。

先在临时目录复现

下面的 Python 例子用于 Linux、macOS 等 Unix 系统,不适用于 Windows 中仍被打开的文件删除语义。它不碰业务目录。先创建 4 MiB 文件,解除路径,再通过仍打开的句柄读取并检查大小;关闭句柄后才清理临时目录。

import os
import tempfile

with tempfile.TemporaryDirectory(prefix="unlink-fd-") as directory:
    path = os.path.join(directory, "payload.bin")
    with open(path, "wb") as f:
        f.write(b"x" * (4 * 1024 * 1024))

    f = open(path, "rb")
    os.unlink(path)
    print("路径存在:", os.path.exists(path))
    print("FD 对应大小:", os.fstat(f.fileno()).st_size)
    print("仍可读取:", f.read(8))
    f.close()

预期路径存在为 False,FD 大小为 4194304,仍能读出八个 x。本次在 macOS 上实际运行得到这些结果;macOS 没有 Linux 的 /proc,所以这里只验证 unlink 与打开 FD 的生命周期,不声称实测了 Linux 命令。Linux 可用 lsof +L1 查找链接数小于 1 的打开文件;再用 readlink /proc/<PID>/fd/<FD> 查看目标,常见结果带有 (deleted)。也可列出 /proc/<PID>/fd/ 并逐个检查。权限、容器 PID 命名空间及进程竞态可能影响可见性;lsof 无结果时,还应确认检查的是发生空间异常的主机/挂载命名空间。

确认后释放空间

先用 df -h 确认文件系统,再结合 lsof +L1 的 PID、FD、大小和命令名定位持有者;核实它确实属于可清理的日志或临时文件。优先让应用按支持的方式重开日志、完成轮转,或在维护窗口正常重启对应服务。进程关闭旧 FD 后,内核即可回收对应数据块;重新检查 df。如果仍有差异,再检查快照、其他进程引用、挂载点和文件系统统计等因素,不能仅凭这一现象认定原因。

不要看到 (deleted) 就盲目 kill:FD 可能承载数据库、队列或正在写入的日志,强杀会造成服务中断、未落盘数据丢失或恢复成本。也不要对 /proc/<PID>/fd/<FD> 直接 truncate:这会改动该打开对象的长度,会丢弃被截掉的数据,可能破坏业务文件格式;原有文件偏移不会随截断改变,后续非追加写入还可能产生空洞,并不等同于让进程关闭引用;更不应把 proc 路径当作安全的清理入口。先辨认文件用途,再通过应用生命周期释放引用。

资料

Linux man-pages 的 unlink(2)、proc_pid_fd(5)、truncate(2) 手册,lsof(8) 手册,以及 Python 标准库 os.remove / os.unlink 文档。正文的 Linux 命令是诊断步骤,未在本次 macOS 实验中运行。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。