获取验证码
Linux执行df查看磁盘使用率爆满,但du统计所有目录文件占用空间很小,核心故障根源是存在大量已rm删除、但业务进程仍持有句柄的文件;可以通过lsof | grep deleted查看占用删除文件的进程,重启对应业务进程或者截断文件释放磁盘空间。
有VMware全系列产品官方资源和定制版资源需求的可以移步:
前段时间一台后端日志存储服务器告警磁盘使用率超过90%,登录服务器执行df -h查看/分区已占用94%,随时可能磁盘写满业务崩溃。
第一时间执行du -sh /*逐层排查目录大小,/var/log、/data等业务目录总占用加起来不足总磁盘容量的40%,剩余一半磁盘空间凭空消失,反复查找大文件、查找扩容快照均无结果。
翻阅Linux磁盘与文件句柄机制文档后找到排查思路:rm删除文件仅移除目录项,若打开该文件的进程持续运行不退出,内核不会释放文件占用的磁盘块。随后执行lsof | grep deleted,查出数十个被删除的超大日志文件,均被Java应用、Nginx进程持续占用,重启对应进程后磁盘空间瞬间释放,df使用率直接回落至40%左右。下面完整拆解底层原理、分步排查流程、临时应急方案与长期规范。
du命令统计逻辑:仅遍历当前目录树中存在的有效文件,只计算能在磁盘目录中检索到的文件大小;已经被rm删除、仅进程持有句柄的文件,目录项已经消失,du完全不会统计这部分占用。
df命令统计逻辑:直接读取磁盘分区块设备总占用,统计内核层面所有正在占用的磁盘块,包含目录中可见文件 + 已删除但句柄未释放的隐藏文件,所以df显示占用远高于du汇总数值。
文件句柄释放规则:Linux内核中,一个文件的磁盘空间会在两个条件全部满足后回收:1、所有目录下该文件的硬链接全部删除;2、所有打开该文件的进程全部关闭文件句柄(进程重启/退出会自动释放句柄)。
高频触发场景:运维直接rm -f 超大日志文件清理磁盘,但Nginx、Java、MySQL等服务未重启,进程持续往已删除文件内追加日志,磁盘空间无法释放。
服务器磁盘容量告警后,运维直接rm删除几个十几GB的日志文件,未重启写入日志的业务进程;
Nginx、后端Java服务后台持续运行,仍然持有已删除日志文件的读写句柄,内核持续保留对应磁盘块;
du仅检索现存目录文件,无法统计句柄占用的已删除文件,导致目录总占用和df磁盘占用差值巨大;
未配置日志轮转logrotate自动截断清理,只能手动rm删除日志,极易出现该类磁盘空间不释放问题。
执行df -h 确认磁盘分区使用率、挂载点,锁定爆满的分区;
执行du -sh /* 汇总根目录所有目录总占用,对比df数值,确认存在大量隐藏占用文件;
执行lsof | grep deleted 筛选所有已删除、但进程持有句柄的文件,输出内容包含:进程PID、进程名称、文件大小、文件路径;
根据lsof输出的PID,确认对应业务服务,区分Nginx、Java、数据库等进程;
临时处理:不重启进程前提下,使用/truncate/ > 原文件路径截断文件,立刻释放磁盘空间;长期根治:正常重启对应业务进程,自动释放所有文件句柄;
处理完成后再次执行df -h,确认磁盘使用率回落,空间成功释放。
通过lsof | grep deleted 找到占用大空间的已删除文件完整路径;
使用输出重定向截断文件,示例:> /var/log/nginx/access.log;该操作不会关闭进程句柄,但会清空文件磁盘块,瞬间释放空间;
批量处理场景:编写简单循环脚本,批量截断所有被删除的日志文件;
临时释放空间后,择业务低峰期重启对应服务,彻底释放句柄,避免后续磁盘再次爆满。
全线服务器配置logrotate日志自动轮转工具,按文件大小/时间自动切割、压缩、删除老旧日志,logrotate内置文件截断逻辑,不会产生句柄占用残留;
禁止运维直接使用rm命令清理正在被业务写入的活跃日志文件,如需清理优先使用截断操作;
监控告警新增lsof deleted文件数量监控,定时检测系统中已删除未释放句柄的文件,数量超标提前推送告警,避免磁盘突然爆满;
容器化业务统一使用容器日志驱动,日志输出至stdout,由宿主机日志收集工具统一管理,减少宿主机本地大日志文件;
制定运维磁盘清理规范:清理业务活跃日志后,必须重启对应服务或截断文件,同步记录操作台账,防止遗忘句柄占用问题。
| 故障现象 | 根因分析 | 标准解决方案 |
|---|---|---|
| df显示磁盘占用95%,du统计全部目录仅占用40%容量,差值巨大 | 大量日志文件rm删除后,业务进程仍持有文件句柄,内核不回收磁盘块 | lsof | grep deleted 查找占用进程,截断文件或重启服务释放空间 |
| lsof查询不到deleted文件,但df和du占用差距依然很大 | 存在挂载点嵌套覆盖、挂载临时文件系统遮挡原目录文件,du无法读取底层文件 | 临时卸载临时挂载目录,重新执行du统计底层真实文件占用 |
| 截断文件后磁盘空间立刻释放,过几小时磁盘又快速涨满 | 业务进程持续往日志文件追加数据,仅截断未重启进程,文件会持续增大 | 业务低峰重启服务彻底释放句柄,同时配置logrotate自动轮转日志 |
| 服务器重启后,df磁盘占用直接恢复正常,空间全部释放 | 服务器重启会杀死所有进程,全部文件句柄强制释放,内核回收所有空闲磁盘块 | 紧急故障可临时重启服务器,生产业务优先截断文件避免停机 |
| logrotate配置完成,但删除日志后依旧存在句柄占用问题 | logrotate未配置copytruncate参数,采用直接删除旧日志方式,进程句柄不释放 | logrotate配置中添加copytruncate,轮转时复制日志后截断原文件,不直接删除 |
1. 误区:rm删除文件后磁盘空间会立刻释放,df数值会同步下降纠正:rm仅删除目录入口,只要有进程打开该文件,磁盘块会持续占用,df占用不会下降,必须释放文件句柄才能回收空间。
2. 误区:磁盘占用异常,只需要逐层du查找大目录就能定位所有占用文件纠正:du只能读取当前目录树存在的文件,已删除仅句柄占用的文件du完全无法统计,出现df/du差值必须使用lsof排查deleted文件。
3. 误区:业务不能重启,无法释放已删除文件占用的磁盘空间纠正:使用> 文件路径 截断操作,无需重启进程,直接清空文件磁盘占用,临时快速释放磁盘空间,适合业务不允许停机的紧急场景。
4. 误区:日志清理直接rm删除最省事,不需要配置logrotate工具纠正:手动rm清理活跃日志极易产生句柄占用、磁盘不释放故障;logrotate自动轮转搭配copytruncate参数,从根源避免该类问题,是生产标准规范。
5. 误区:lsof看不到deleted文件,就代表不存在隐藏磁盘占用纠正:除了句柄占用文件,挂载点嵌套、裸设备数据、数据库回滚日志、内核临时文件也会造成df/du占用差值,lsof无输出时需要排查挂载覆盖场景。