首页/系统/Linux 内核与性能调优速查/已删除仍占空间的文件

已删除仍占空间的文件

df 显示满、du 却对不上:进程仍持有已删除文件句柄;lsof +L1 按链接数筛选,释放需要进程重新打开或重启。

已删除仍占空间是怎么回事

典型现象是 df 显示文件系统接近写满,du 从根目录逐层统计出来的占用却对不上。原因是进程仍持有已被删除文件的打开句柄:文件名从目录项消失,但只要还有进程引用该 inode,数据块就不会归还。lsof +L1 用链接数小于 1 的条件筛出这类文件,空间能否释放取决于持有进程是否重新打开文件或退出。

基本信息

适用平台Linux(lsof 包)
筛选命令lsof +L1,或 lsof | grep -i deleted
关键列COMMAND、PID、USER、NLINK、SIZE/OFF、NAME
释放方式重启或 reload 持有进程,必要时按 fd 清空
排查前提先做 df 与 du 的差量对比,再执行 lsof

典型使用场景

  • 磁盘告警但 du 找不到大文件,确认是否为已删除句柄占用
  • 日志轮转后空间没有释放,确认写日志进程是否重新打开了新文件
  • 定位扩容迟迟不生效的原因,找出长期持有句柄的进程
  • 容器排障:容器内进程持有的句柄在宿主上同样占空间
  • 发布回滚后确认旧版本进程退出、空间是否真正归还

排查命令

排查命令
df -h /data                              # 先确认文件系统使用率
du -xh --max-depth=1 /data | sort -h | tail   # 逐层找占用,与 df 对不上就继续
sudo lsof +L1 | sort -k7 -n | tail -20   # 按大小排序查看已删除句柄
sudo lsof +L1 | awk '{print $1,$2,$7,$9}' # 提取进程、大小与路径
ls -l /proc/12345/fd | grep deleted       # 核对指定进程持有的句柄

输出逐列读法

列含义判读
COMMAND持有句柄的进程名定位到具体服务
PID进程号用于确认是否可以安全重启
USER进程属主判断影响范围与沟通对象
NLINK硬链接数为 0 表示文件已从目录中移除
SIZE/OFF文件大小或偏移量数值大的通常是空间占用主因
NAME文件路径末尾带 (deleted) 即已删除
清空句柄前必须先确认文件类型:正在写入的日志可以用 truncate -s 0 /proc/<pid>/fd/<fd> 立即归还空间;对数据库或消息队列文件这样做会破坏数据,正确做法是重启进程或触发它重新打开文件。
lsof 输出量大时排序会明显变慢,在空间已经打满的机器上可能长时间无响应,建议先加上设备过滤(lsof +L1 /data)限制扫描范围。

易错点

  • 对数据库文件执行 truncate 清空 fd,会直接造成数据损坏,属于不可逆操作
  • 直接重启进程而不看依赖关系,业务会中断且空间未必归还(父进程或子进程仍持有句柄)
  • 只在容器内执行 lsof,看不到宿主命名空间里持有的句柄,排查会得出错误结论
  • 把 df 与 du 的差量一律当成句柄泄漏,忽略了保留块、稀疏文件与挂载嵌套等其他原因

数据来源与参考

  • lsof 官方文档
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌