已删除仍占空间是怎么回事
典型现象是 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)限制扫描范围。