清理服务器磁盘时,不少人会遇到一个让人抓狂的情况:df -h 显示磁盘使用率已经100%,可你用 du 从上到下把目录翻了个遍,也找不到那个把磁盘塞满的大文件。磁盘空间到底去哪了?答案往往藏在一个反直觉的地方:已经被删除、却仍被运行中的进程打开着的文件。

为什么删除了文件空间却不释放
在Linux中,进程打开文件后会持有该文件的文件描述符。即使你执行 rm 把文件名从目录里删掉,只要还有进程握着这个文件的句柄,文件的数据块就不会真正释放,磁盘空间也一直显示被占用。这在日志文件、数据库临时文件、被反复写入的缓存文件上尤其常见——日志被删除后进程仍不断往里写,空间自然越占越多。
用du先排除正常的空间占用
排查之前,先用 du 确认常规目录里确实没有大文件,排除自己漏看的情况。注意 du 默认不统计隐藏文件,也没有统计被删除文件:
# 查看根分区下各一级目录占用,从大到小
cd / && du -xsh */ 2>/dev/null | sort -rh | head -15
# 只看具体目录(含隐藏文件)
du -sh /var/log /tmp /var/lib 2>/dev/null | sort -rh
用lsof找出占用已删除文件的进程
确认常规占用没问题后,用 lsof 列出所有已删除但仍被打开的文件,这是定位问题的关键一步:
# 列出所有被删除但仍在使用的文件
lsof +L1
# 只看删除的大文件(按大小排序可加 | sort -k7 -h)
lsof +L1 | sort -k7 -h | tail -15
输出中 SIZE 一列是该文件占用的空间,NAME 里带 (deleted) 标记的就是已删除文件。找到大文件对应的 PID 和进程名后,处置方式有两种:如果该进程可以安全重启(如nginx、php-fpm的日志),重启即可释放;如果是不便中断的服务(如数据库),可以先确认业务侧是否还需要旧日志,再决定是重启还是保留。
# 查看某PID打开的已删除文件
ls -l /proc/PID/fd 2>/dev/null | grep deleted
# 确认进程信息后重启服务释放空间(示例)
systemctl restart nginx
如何避免这类问题再次发生
- 日志类文件使用logrotate轮转而不是直接rm,轮转时通过信号让程序重新打开日志文件;
- 清理被占用的日志前,先了解对应服务的日志机制,避免误清;
- 把日志、临时文件挂载到独立分区,隔离业务数据与系统空间;
- 建立磁盘使用率告警,在接近阈值时提前处理,而不是等100%了再排查。
相关问答FAQs
- 问:重启服务后空间会立刻释放吗?答:会,进程退出或重新打开文件后,已删除文件的数据块随即被回收,df -h能看到空间回落。
- 问:lsof没装怎么办?答:CentOS可用yum install -y lsof安装;临时方案可查看 /proc/*/fd 下带(deleted)的链接逐一排查。
- 问:数据库删了日志也释放不了空间怎么办?答:不要在生产库上直接删除日志文件,应使用数据库自身的日志清理命令或按官方文档操作,必要时联系DBA处理。
磁盘空间排查要学会两条腿走路:du 找正常文件的占用,lsof 找已删除文件的占用。遇到df满而du找不到的情况,先别急着翻目录,用 lsof +L1 看一眼往往立刻就有答案。把这个命令记进你的排查手册,下次遇到就不会再对着磁盘干瞪眼了。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!