文件已删除空间不释放:用 lsof 和 /proc 排查文件描述符
线上常见两类和文件描述符相关的故障:日志或数据文件已经 rm 掉,df 却几乎不降;进程报 Too many open files,新连接或新日志都打不开。两者都不是单纯的磁盘问题,而是进程还握着已打开的文件。下面按现场排查来写。
先确认是不是「删了但仍被占用」
Linux 里 rm 只是去掉目录项。只要还有进程打开着这个文件,inode 和数据块就不会回收,df 看起来空间没释放。用下面这条找出链接数为 0、但仍被打开的文件:
lsof +L1
+L1 列出链接数小于 1 的已打开文件,输出里常见 (deleted),同时给出 PID 和文件描述符编号。锁定进程后可以再看:
lsof -p <PID>
ls -l /proc/<PID>/fd
/proc/<PID>/fd 里,已删除文件会显示为 文件名 (deleted),符号链接指向的就是仍占用空间的那份数据。对照 lsof +L1 的 SIZE 和 df,就能确认是谁在占着空间。
不要再删,优先截断
文件已经没有目录项,再执行一次 rm 没有意义。要立刻腾空间又不能马上重启进程时,应对准那个还开着的描述符做截断,而不是去删一个已经不存在的路径:
: > /proc/<PID>/fd/<FD>
这会把已删除但仍打开的文件长度打成 0,块空间通常马上会回来。注意:若进程不是以追加方式写,而是记住旧偏移再写入,截断后文件仍可能重新胀大。截断是应急,根治仍是让进程关闭描述符或滚动到新文件后再重启、reload。
再查 Too many open files
进程打不开新文件或 socket 时,先看它的限制和当前持有量:
ulimit -n
cat /proc/<PID>/limits
ls /proc/<PID>/fd | wc -l
lsof -p <PID> | wc -l
ulimit -n 只反映当前 shell 的软限制,对已经由 systemd 拉起的服务往往不准。应看 /proc/<PID>/limits 里的 Max open files,或在单元中确认 LimitNOFILE。lsof -p 和 /proc/<PID>/fd 用来区分是套接字泄漏、日志没关,还是确有大量合法连接。
不要一上来把 LimitNOFILE 调到很大。先修泄漏:确认连接是否关闭、文件是否成对 open/close。确实需要更高上限时,再在单元里设置 LimitNOFILE,执行 daemon-reload 并重启服务,使新限制生效。系统级还有 fs.file-max,那是整机上限,和进程软限制不是一回事。
小结
空间不释放,先用 lsof +L1 找已删除但仍打开的文件,结合 lsof -p 和 /proc/PID/fd 确认占用进程;应急用截断描述符释放空间,而不是再删一次。遇到 Too many open files,用 ulimit -n、进程 limits 和 LimitNOFILE 核对上限,用打开的描述符列表找泄漏。把文件描述符当成和磁盘容量一样要监控的指标,这两类故障会好查得多。
- 点赞
- 收藏
- 关注作者
评论(0)