一键登录 更安全快捷
邮箱登录
我已阅读并接受 用户协议 隐私政策

Linux系统df查看磁盘使用率很高,但du查询占用极低完整排错方案

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%左右。下面完整拆解底层原理、分步排查流程、临时应急方案与长期规范。

1.1 df与du统计逻辑差异、删除文件不释放空间底层原理

  • du命令统计逻辑:仅遍历当前目录树中存在的有效文件,只计算能在磁盘目录中检索到的文件大小;已经被rm删除、仅进程持有句柄的文件,目录项已经消失,du完全不会统计这部分占用。

  • df命令统计逻辑:直接读取磁盘分区块设备总占用,统计内核层面所有正在占用的磁盘块,包含目录中可见文件 + 已删除但句柄未释放的隐藏文件,所以df显示占用远高于du汇总数值。

  • 文件句柄释放规则:Linux内核中,一个文件的磁盘空间会在两个条件全部满足后回收:1、所有目录下该文件的硬链接全部删除;2、所有打开该文件的进程全部关闭文件句柄(进程重启/退出会自动释放句柄)。

  • 高频触发场景:运维直接rm -f 超大日志文件清理磁盘,但Nginx、Java、MySQL等服务未重启,进程持续往已删除文件内追加日志,磁盘空间无法释放。

1.2 本次故障直接触发诱因

  1. 服务器磁盘容量告警后,运维直接rm删除几个十几GB的日志文件,未重启写入日志的业务进程;

  2. Nginx、后端Java服务后台持续运行,仍然持有已删除日志文件的读写句柄,内核持续保留对应磁盘块;

  3. du仅检索现存目录文件,无法统计句柄占用的已删除文件,导致目录总占用和df磁盘占用差值巨大;

  4. 未配置日志轮转logrotate自动截断清理,只能手动rm删除日志,极易出现该类磁盘空间不释放问题。

二、标准分步排查流程(定位句柄占用文件)

  1. 执行df -h 确认磁盘分区使用率、挂载点,锁定爆满的分区;

  2. 执行du -sh /* 汇总根目录所有目录总占用,对比df数值,确认存在大量隐藏占用文件;

  3. 执行lsof | grep deleted 筛选所有已删除、但进程持有句柄的文件,输出内容包含:进程PID、进程名称、文件大小、文件路径;

  4. 根据lsof输出的PID,确认对应业务服务,区分Nginx、Java、数据库等进程;

  5. 临时处理:不重启进程前提下,使用/truncate/ > 原文件路径截断文件,立刻释放磁盘空间;长期根治:正常重启对应业务进程,自动释放所有文件句柄;

  6. 处理完成后再次执行df -h,确认磁盘使用率回落,空间成功释放。

三、分层解决方案:临时应急不重启进程、长期标准化日志清理方案

3.1 现场临时应急方案(业务不能重启,快速释放磁盘)

  1. 通过lsof | grep deleted 找到占用大空间的已删除文件完整路径;

  2. 使用输出重定向截断文件,示例:> /var/log/nginx/access.log;该操作不会关闭进程句柄,但会清空文件磁盘块,瞬间释放空间;

  3. 批量处理场景:编写简单循环脚本,批量截断所有被删除的日志文件;

  4. 临时释放空间后,择业务低峰期重启对应服务,彻底释放句柄,避免后续磁盘再次爆满。

3.2 企业长期标准化根治优化方案

  1. 全线服务器配置logrotate日志自动轮转工具,按文件大小/时间自动切割、压缩、删除老旧日志,logrotate内置文件截断逻辑,不会产生句柄占用残留;

  2. 禁止运维直接使用rm命令清理正在被业务写入的活跃日志文件,如需清理优先使用截断操作;

  3. 监控告警新增lsof deleted文件数量监控,定时检测系统中已删除未释放句柄的文件,数量超标提前推送告警,避免磁盘突然爆满;

  4. 容器化业务统一使用容器日志驱动,日志输出至stdout,由宿主机日志收集工具统一管理,减少宿主机本地大日志文件;

  5. 制定运维磁盘清理规范:清理业务活跃日志后,必须重启对应服务或截断文件,同步记录操作台账,防止遗忘句柄占用问题。

四、高频故障排错清单(现场实操各类磁盘空间异常场景)

故障现象根因分析标准解决方案
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无输出时需要排查挂载覆盖场景。

用户留言 User Comments