news 2026/7/21 6:58:02

服务器磁盘一夜写满 100GB,根因是一行 DEBUG 日志

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
服务器磁盘一夜写满 100GB,根因是一行 DEBUG 日志

服务器磁盘一夜写满 100GB,根因是一行 DEBUG 日志

凌晨 3 点,服务器磁盘使用率突然达到 100%。

接口开始报错,日志写不进去,应用重启也失败。

最后发现,不是文件上传,也不是数据库备份,而是一行打印完整请求体的DEBUG日志,一晚上写了 100GB。


一、事故现场

凌晨告警连续响起:

磁盘使用率:72% -> 100% 接口错误率:0.2% -> 18% 日志写入:No space left on device 应用重启:失败

登录服务器后,第一条命令:

df-h

结果显示:

Filesystem Size Used Avail Use% Mounted on /dev/vdb1 200G 200G 0 100% /data

磁盘确实满了。

应用还没有完全停止,但已经出现各种看起来毫不相关的异常:

日志无法写入 临时文件创建失败 上传接口失败 定时任务执行异常 应用无法生成新的 PID 文件

磁盘写满后,最危险的地方就在这里:

它不会只影响日志,而是可能让整台机器上的多个服务一起异常。


二、先分清:空间满了,还是 inode 用完了

df -h查看的是磁盘空间。

还要检查 inode:

df-i

如果磁盘容量还有很多,但 inode 使用率已经 100%,通常是产生了海量小文件。

这次的情况比较直接:容量已经耗尽,inode 正常。

下一步从挂载点开始找最大目录:

du-xhd1/data|sort-h

很快发现:

3.2G /data/upload 8.7G /data/backup 176G /data/logs

继续向下查:

du-xhd1/data/logs|sort-h

最终定位到订单服务:

168G /data/logs/order-service

查找最大的日志文件:

find/data/logs/order-service-typef-size+1G-printf'%s %p\n'\|sort-nr\|head-20

其中当天的app.log已经达到 103GB。


三、100GB 日志到底写了什么?

不要直接打开整个文件。

先查看末尾少量内容:

tail-n100/data/logs/order-service/app.log

屏幕上反复出现同一种日志:

DEBUG c.example.order.CallbackService callback request: {"orderId":"...","items":[...],"ext":{...}}

每一条都打印了完整回调请求。

请求里包含商品明细、营销信息和扩展字段,平均一条大约 6KB。

高峰期回调 QPS 接近 200:

6KB × 200 × 86400 ≈ 103GB/天

100GB 不是某一刻突然产生的。

它只是以每秒 1MB 多一点的速度,安静地写了一整天。

最终定位到代码:

log.debug("callback request: {}",objectMapper.writeValueAsString(request));

这行代码已经存在一段时间,以前却没有出事。

真正让它爆炸的是当天的一次配置变更:

logging:level:com.example.order:DEBUG

为了临时排查一个回调问题,有人把整个订单包的日志级别调整成了DEBUG

问题处理完后,配置没有恢复。

同时日志只按天切分,没有限制单个文件大小,也没有限制历史日志总量。

三个条件叠加,最终把磁盘写满:

生产误开 DEBUG ↓ 每个请求打印完整 JSON ↓ 高峰期每秒写入约 1.2MB ↓ 日志没有大小和总量上限 ↓ 磁盘使用率达到 100% ↓ 应用和同机服务陆续异常

四、为什么删了日志,磁盘空间还没回来?

事故处理中,有人第一时间执行:

rmapp.log

文件在目录中消失了,但df -h仍然显示磁盘 100%。

这是因为 Java 进程还持有这个文件的打开句柄。

在 Linux 中,目录项被删除,不代表正在使用该文件的进程已经释放空间。

可以检查已删除但仍被进程占用的文件:

lsof+L1

可能看到:

java 18472 app 217w REG 253,17 103G 0 /data/logs/order-service/app.log (deleted)

此时需要让进程关闭对应文件描述符,例如在完成止损和流量处理后,正常重启应用。

如果业务暂时不能重启,也可以评估使用truncate清空当前日志:

truncate-s0/data/logs/order-service/app.log

但这会直接丢失日志,执行前必须:

确认目标文件绝对路径 保存必要的故障样本 确认日志是否仍有审计价值 确认没有选错服务或文件

线上不要使用模糊通配符批量删除,更不要为了腾空间随意清理数据库、上传文件和未知目录。


五、事故发生时,正确的止损顺序

这类事故不能只做“删日志”一个动作。

我更建议按照下面的顺序处理。

1. 先停止继续写爆

把对应包的日志级别恢复到INFO,或者临时关闭问题日志。

如果通过配置中心动态调整,需要确认配置已经在所有实例生效。

2. 保留必要证据

保存:

问题日志样本 配置变更记录 磁盘监控曲线 异常开始时间 日志增长速度

否则空间恢复后,很难还原根因。

3. 清理确定可以删除的文件

优先处理已经归档、确定过期的日志。

对于正在写入的文件,先确认进程句柄,避免出现“文件删了,空间仍未释放”。

4. 确认应用恢复

至少检查:

df-hdf-i

同时观察接口成功率、应用日志、进程状态和同机服务。

5. 再处理永久修复

应急清理只是让服务暂时恢复。

不修改日志代码、滚动策略和告警,第二天磁盘还会再次写满。


六、第一处修复:不要打印完整请求体

原来的代码:

log.debug("callback request: {}",objectMapper.writeValueAsString(request));

至少存在四个问题:

请求体可能很大 序列化动作已经提前执行 请求中可能包含敏感信息 高 QPS 下日志量会被成倍放大

更合理的是只记录定位问题需要的字段:

log.info("payment callback, requestId={}, orderId={}, itemCount={}",request.getRequestId(),request.getOrderId(),request.getItems().size());

如果完整报文确实需要保留,也应该考虑:

字段脱敏 限制最大长度 按比例采样 只在异常时记录必要内容 写入专门的审计存储 设置明确保留期限

日志不是数据备份系统,也不应该承担完整业务报文存档。


七、第二处修复:同时限制文件大小、保留时间和总量

只配置“每天切一个文件”并不够。

如果一天产生 100GB,午夜之前它仍然是一个 100GB 文件。

使用 Spring Boot 默认 Logback 时,可以根据项目版本配置类似策略:

logging:file:name:/data/logs/order-service/app.loglevel:root:INFOcom.example.order:INFOlogback:rollingpolicy:file-name-pattern:/data/logs/order-service/app.%d{yyyy-MM-dd}.%i.log.gzmax-file-size:200MBmax-history:14total-size-cap:5GBclean-history-on-start:true

这几个参数解决不同问题:

max-file-size:限制单个日志文件 max-history:限制保留周期 total-size-cap:限制归档日志总量 clean-history-on-start:应用启动时清理过期归档

配置名称和默认值可能随 Spring Boot、Logback 版本变化,上线前应根据项目实际版本验证滚动和清理行为。

如果使用自定义logback-spring.xml,可以配置SizeAndTimeBasedRollingPolicy

<appendername="FILE"class="ch.qos.logback.core.rolling.RollingFileAppender"><file>/data/logs/order-service/app.log</file><rollingPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>/data/logs/order-service/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern><maxFileSize>200MB</maxFileSize><maxHistory>14</maxHistory><totalSizeCap>5GB</totalSizeCap></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n</pattern></encoder></appender>

maxHistorytotalSizeCap应该同时设置。

保留 14 天,并不意味着磁盘一定安全。如果每天产生 20GB,仍然可能保留数百 GB;总量上限才是最后一道边界。


八、第三处修复:不要等到 100% 才告警

磁盘告警至少应该分级:

70%:提醒,观察增长速度 80%:告警,开始定位大目录 90%:严重告警,立即处理

除了使用率,还应该监控:

磁盘剩余空间 inode 使用率 每小时增长速度 日志目录大小 单个文件增长速度 应用日志写入失败次数

如果磁盘从 70% 增长到 80% 用了一小时,就不能等它真正达到 90% 才处理。

增长速度往往比当前百分比更早暴露问题。


九、日志上线前检查清单

[ ] 生产环境没有误开 DEBUG 或 TRACE [ ] 不打印完整密码、Token、身份证和银行卡号 [ ] 不在高频循环中打印大对象 [ ] 请求体和响应体日志有长度限制 [ ] 异常日志不会重复打印多次 [ ] 单个日志文件有大小上限 [ ] 日志同时按时间和大小滚动 [ ] 历史日志有保留期限 [ ] 所有归档日志有总量上限 [ ] GC、访问和应用日志分别管理 [ ] 磁盘容量和 inode 都有告警 [ ] 已验证日志滚动与自动清理真正生效

总结

这次事故表面上是磁盘写满,真正的故障链路是:

临时排查打开 DEBUG -> 问题解决后忘记恢复 -> 每个请求打印完整 JSON -> 日志每天增长约 100GB -> 没有单文件和总量上限 -> 磁盘达到 100% -> 应用和同机服务陆续异常

一行日志不会立刻让系统崩溃。

但当它处在高频路径、打印大对象,并且没有任何容量边界时,一晚上足以写满整块磁盘。

记住三个原则:

日志只记录定位问题需要的信息;日志文件必须有滚动和总量上限;磁盘必须在写满之前告警。


如果你遇到服务器磁盘写满、Java 服务异常、日志滚动失效,或者需要协助安装部署 Spring Boot、MySQL、Redis、Nginx,可以关注我, 联系我。

简单问题、基础安装和初步排查,我可以免费帮忙看一下。发送配置和日志前请先脱敏,不要提供密码、Token、私钥与用户隐私数据。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 6:56:16

深入解析AM263P ADC高级特性:中断溢出、PPB与安全检查器实战

1. 项目概述在嵌入式系统&#xff0c;尤其是工业控制、汽车电子和电力监测这类对实时性和可靠性要求极高的领域&#xff0c;模数转换器&#xff08;ADC&#xff09;的性能直接决定了整个系统的“感知”能力。我们常常需要它不仅能快速、准确地采集电压、电流、温度等模拟信号&a…

作者头像 李华
网站建设 2026/7/21 6:54:31

Unity整合KinectForUnity 2.9插件:体感交互开发全流程指南

1. 项目概述&#xff1a;Kinect与Unity的“老友记”与新篇章如果你是一位Unity开发者&#xff0c;并且对体感交互、动作捕捉或者非接触式人机交互感兴趣&#xff0c;那么Kinect这个名字对你来说一定不陌生。它曾经是微软在游戏和交互领域投下的一颗重磅炸弹&#xff0c;虽然其硬…

作者头像 李华
网站建设 2026/7/21 6:54:13

深入解析红黑树在TreeMap中的实现与应用

1. 为什么说红黑树是TreeMap的灵魂 第一次接触TreeMap源码时&#xff0c;我也被那满屏的left、right、color字段绕晕过。直到亲手画了十几张红黑树的演变图&#xff0c;才突然理解为什么Java集合框架要选择这个数据结构作为TreeMap的底层实现。 红黑树本质上是一棵特殊的二叉搜…

作者头像 李华
网站建设 2026/7/21 6:50:43

TMS320F28004x DMA模块架构解析与驱动开发实战

1. DMA模块核心架构与设计思路拆解 在嵌入式实时控制系统中&#xff0c;CPU的算力是宝贵的资源。当系统需要频繁地在内存与外设之间搬运数据时&#xff0c;例如ADC连续采样、SPI/UART通信数据收发&#xff0c;如果这些操作都由CPU通过软件循环来完成&#xff0c;会大量占用CPU时…

作者头像 李华
网站建设 2026/7/21 6:50:09

C++模拟算法入门:从“津津的储蓄计划”掌握循环与条件判断

1. 项目概述&#xff1a;从“津津的储蓄计划”看编程与生活的结合最近在洛谷上看到一个挺有意思的题目&#xff0c;编号P1089&#xff0c;叫“津津的储蓄计划”。乍一看标题&#xff0c;还以为是什么理财软件或者生活管理App&#xff0c;点进去才发现&#xff0c;这其实是一个经…

作者头像 李华
网站建设 2026/7/21 6:50:01

敏捷开发聊天机器人:LLM与Prompt工程实战

1. 项目概述&#xff1a;当敏捷遇上聊天机器人开发三年前我接手第一个企业级聊天机器人项目时&#xff0c;团队花了三个月才产出第一个可演示版本。而去年我们用新方法&#xff0c;在两周内就完成了从零到生产环境部署的全流程。这种转变的核心&#xff0c;就在于放弃了传统&qu…

作者头像 李华