已删除文件占空间是什么
磁盘显示已满,但用 du 逐层统计却找不到对应的大文件,最常见的原因是进程仍持有已被删除文件的句柄:文件在目录里消失了,内核却没有释放数据块。日志被误删、轮转配置写错、应用重开日志失败都会造成这种现象。
基本信息
| 场景 | df 与 du 显示不一致,空间没有释放 |
|---|---|
| 组合 | lsof +L1 与 /proc/PID/fd 反查 |
| 处理 | 让持有者重开文件或重启进程 |
| 关键 | 先确认持有者,再决定动作 |
典型使用场景
- 空间异常:磁盘满而 du 统计不到,优先怀疑已删除但被打开的文件
- 轮转后空间未降:清理脚本删了日志,进程却没重开文件
- 重启前评估:确认能释放多少空间,以及重启能否被业务接受
- 容器环境:句柄属于容器内的进程,宿主上看不到对应文件
- 事后复盘:定位是哪次误删导致空间未释放,修正清理脚本
找出占用者
找出占用者
lsof +L1 | sort -k7 -rn | head -n 10 # 列出已删除但被打开的文件
lsof +L1 | awk '$7 > 1073741824' | head # 只关注大于 1G 的条目
ls -l /proc/1234/fd | grep deleted | head # 从进程描述符反查,速度更快
du -sh /proc/1234/fd 2>/dev/null # 粗略查看该进程持有的空间释放空间
释放空间
ls -l /proc/1234/fd | grep deleted # 确认持有的描述符编号
kill -USR1 1234 # 很多服务用该信号重开日志(如 nginx)
ls -l /proc/1234/fd | grep deleted # 复核是否已释放
systemctl restart myapp # 或重启持有者进程(业务允许时)现象与处理
| 现象 | 原因 | 处理 |
|---|---|---|
| df 满而 du 少 | 已删除文件仍被进程打开 | 定位持有者后重开或重启 |
| 轮转后空间不降 | 日志被删除但进程未重开文件 | 改用 copytruncate 或发信号重开 |
| 容器内看不到 | 句柄属于容器里的进程 | 进入容器或按宿主进程定位 |
| 释放后立刻涨回 | 应用仍在写同一个文件名 | 先修轮转配置再释放 |
把往描述符路径写数据当作常规手段有风险,操作前必须确认应用行为,不要对不熟悉的进程随意操作。
轮转配置里用 copytruncate 可以从根上避免这个问题:不改变文件本身,进程继续写同一个文件,不会产生已删除句柄。
释放大文件时磁盘 IO 会有瞬时波动,业务高峰期操作要先评估影响。