因为文件被进程占用时删除仅解除链接,内核保留数据块;lsof显示(deleted)说明fd仍打开,空间未释放,需重启服务或安全终止进程。
为什么 lsof | grep deleted 找到的文件删不掉还占空间
因为 Linux 文件系统里,“删除”只是解除文件名到 inode 的链接,如果进程仍在打开该文件(lsof 能看到),内核会保留其数据块,磁盘空间不会释放。常见于日志轮转没重启服务、程序未关闭 fd 就 unlink 了文件。
这类文件在 lsof 输出中表现为路径带 (deleted),但 ls 查不到,du 也统计不到——它们只活在进程的 file descriptor 里。
- 典型输出:
nginx 1234 www-data 10u REG 253,1 128765432 123456 /var/log/nginx/access.log (deleted) - 注意
10u是 fd 编号,REG表示普通文件,数字128765432是字节数(可直接换算成 MB) - 不能用
rm删除,也不能清空/proc/PID/fd/10(会报Text file busy或权限拒绝)
如何安全释放这些已删除但仍被占用的空间
核心思路:让持有该 fd 的进程主动关闭它,或终止进程。不能暴力 echo > /proc/PID/fd/N,那会破坏进程行为甚至导致崩溃。
- 优先尝试优雅重启服务:
systemctl reload nginx或kill -USR1 $(pgrep nginx)(很多服务支持 USR1 重载日志) - 若必须终止进程,用
kill -15 PID(SIGTERM),等几秒再kill -9 PID(仅当 SIGTERM 无效时) - 确认释放:执行后再次运行
lsof | grep deleted,对应行应消失;同时df显示可用空间回升 - 不要尝试
cp /dev/null > /proc/PID/fd/N—— 大部分情况会失败,且可能触发进程异常写入
一键定位并提示大文件的检查脚本
下面这个 shell 片段能快速列出按大小排序的 top 10 占用型 deleted 文件,并给出对应 kill/reload 建议: