Spring Boot 日志把云服务器磁盘写满了:Logback 滚动策略与日志轮转实战

举报
yd_213686897 发表于 2026/11/13 07:32:00 2026/11/13
【摘要】 一、故障现象:服务突然访问不了,重启也不行一台 Flexus 云服务器上跑着一个 Spring Boot 应用,JAR 包直接启动,内嵌 Tomcat 监听 8080 端口,前面再挂一层 Nginx 反向代理。某天早上服务突然访问不了,登录服务器重启应用,发现应用根本起不来,控制台提示磁盘空间不足。当时第一反应是磁盘被业务数据占满了,但这台服务器只跑了这一个应用,没有数据库、没有大文件。真...

一、故障现象:服务突然访问不了,重启也不行

一台 Flexus 云服务器上跑着一个 Spring Boot 应用,JAR 包直接启动,内嵌 Tomcat 监听 8080 端口,前面再挂一层 Nginx 反向代理。某天早上服务突然访问不了,登录服务器重启应用,发现应用根本起不来,控制台提示磁盘空间不足。

当时第一反应是磁盘被业务数据占满了,但这台服务器只跑了这一个应用,没有数据库、没有大文件。真正的原因查出来后,才发现是日志把磁盘写满了。

二、定位:三条命令找到罪魁祸首

第一步,看整体用量。

df -h

根分区 / 的使用率已经到了 100%,可用空间为 0。磁盘满了之后,不光应用起不来,系统写临时文件、写新的日志都会失败。

第二步,逐层下钻找大目录。

du -sh /* | sort -rh | head -5

结果指向了应用日志所在的目录。

第三步,看目录里最大的文件。

du -sh /opt/app/logs/* | sort -rh | head -5
ls -lh /opt/app/logs/

一个 app.log 就占了几十 GB。日志文件从应用上线那天起就没有清理过,一直在同一个文件里追加。

这里有一个容易踩的坑:日志文件正在被应用进程占用时,直接 rm 删除并不会释放磁盘空间,因为文件句柄还被进程持有,删除后空间依然被占用。应急处理要清空文件内容而不是删除文件:

truncate -s 0 /opt/app/logs/app.log

或者重启应用,让进程释放旧句柄。

三、根因:Spring Boot 默认日志没有滚动

Spring Boot 默认使用 Logback,默认配置只往一个文件里写,不做滚动、不做删除。只要应用长期运行,日志只会越写越大。

加速写满的因素通常有三个:

  1. 日志级别开得太低,生产环境还开着 DEBUG,框架内部日志海量输出;
  2. 定时任务、健康检查每隔几秒就打一条日志,日积月累非常可观;
  3. 某个接口的异常被反复捕获又反复打印堆栈,一条异常能打几十行。

磁盘空间是有限的,日志无限增长,写满只是时间问题。

四、根治:Logback 按大小加时间滚动

正确的做法是让日志按天和大小自动滚动,并设置总容量上限。logback-spring.xml 的关键配置:

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>/opt/app/logs/app.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>/opt/app/logs/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <maxFileSize>50MB</maxFileSize>
        <maxHistory>30</maxHistory>
        <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

几个参数的含义:

  • maxFileSize:单个文件超过 50MB 就滚动出一个新文件;
  • maxHistory:只保留最近 30 天的归档日志,更早的自动删除;
  • totalSizeCap:所有归档日志加起来不超过 3GB,超过就从最老的开始删,这是防止写满磁盘的最后一道闸。

同时把生产环境的日志级别收紧到 INFO,只保留必要的业务日志,DEBUG 只在排查问题时临时开启。

五、第二道防线:系统级 logrotate

对于不走 Logback 的日志,比如 Nginx 的访问日志、应用的启动脚本输出,可以用系统自带的 logrotate 做兜底。在 /etc/logrotate.d/app 里写:

/opt/app/logs/*.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    copytruncate
}

copytruncate 的作用是先复制再清空原文件,避免正在写日志的进程持有旧文件句柄导致空间不释放。

六、验证:改完要确认真的生效

配置改完重新打包部署后,验证三件事:

  1. ls -lh 看日志目录,确认出现了按日期滚动的新文件;
  2. df -h 看根分区使用率回落到正常范围;
  3. 故意把 maxFileSize 临时设小一点,跑一段时间,确认日志确实会滚动、旧文件确实会被删除。没有验证的配置等于没有配置。

七、预防:磁盘用量要纳入日常巡检

  • 每周看一次 df -h,或者配一个定时任务把磁盘用量打到巡检表里;
  • 云服务器磁盘使用率告警阈值设在 80%,用到 85% 就处理,不要等到 100% 再抢修;
  • 日志级别、滚动策略写进部署清单,新服务上线时顺带检查一遍。

小结

日志写满磁盘的故障,表面看是磁盘不够,根子是日志没有生命周期管理。应急时用 truncate 清空被占用的日志文件先恢复服务,根治靠 Logback 的大小加时间滚动策略配上 totalSizeCap 上限,再用 logrotate 和磁盘告警做两道防线。把这三层做齐,同样的故障就不会再来第二次。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。