1. 问题背景与现象分析
那天早上,我像往常一样打开云服务器监控面板,突然发现一台关键业务服务器的系统盘使用率飙升至100%。这台服务器的配置是4核CPU、4G内存、40G系统盘,运行着一个Java Spring Boot应用,使用systemd进行服务管理。监控面板显示的几个关键指标让我瞬间警觉:
- 系统盘使用率100%:40G空间全部耗尽
- CPU使用率100%:持续满载状态
- 内存使用率67%:尚在可控范围
- 系统盘IO写入5MB/s:持续高负载
应用响应速度明显变慢,部分接口甚至出现超时。由于业务高峰期即将到来,扩容或更换服务器都来不及,我必须立即找出问题根源并解决。
2. 问题定位与紧急处理
2.1 快速定位磁盘占用源头
我首先使用以下命令查看磁盘使用情况:
bash复制df -h /
du -sh /* 2>/dev/null
结果显示根分区/dev/vda2已用满40G,而/var目录独占约33G空间。继续深入查看:
bash复制cd /var && du -sh * 2>/dev/null
发现/var/log目录占用了约32G空间。进一步检查日志文件:
bash复制cd /var/log && du -sh * 2>/dev/null
最终锁定罪魁祸首:
syslog:约11Gsyslog.1:约21Gjournal:约938M
2.2 紧急释放磁盘空间
在深入分析原因前,必须先释放磁盘空间,否则很多诊断命令都无法执行。我采取了以下措施:
bash复制# 清空当前syslog但保留文件
sudo truncate -s 0 /var/log/syslog
# 删除轮转的大文件
sudo rm /var/log/syslog.1
# 清理所有轮转备份
sudo rm -f /var/log/syslog.*
sudo rm -f /var/log/syslog.*.gz
# 确认空间释放
df -h /
操作后,系统盘使用率从100%降至约19%,可用空间恢复到31G左右。
3. 问题根源分析
3.1 日志链路梳理
通过分析日志流转路径,我理清了问题产生的完整链条:
- 应用层:Spring Boot应用使用Logback输出日志到控制台(stdout/stderr)
- systemd层:服务配置了
StandardOutput=journal和StandardError=journal - rsyslog层:Ubuntu系统默认配置将journal日志转存到
/var/log/syslog - logrotate层:默认配置按天轮转,未设置大小限制
3.2 关键问题点
- 日志无限增长:应用持续输出日志到控制台,经systemd和rsyslog层层转发,最终全部堆积在syslog
- 轮转机制失效:默认logrotate配置未设置size参数,导致syslog文件可以无限增长
- 权限配置问题:后续调整logrotate时遇到的权限问题加剧了处理难度
4. 系统级解决方案
4.1 切断日志来源
首先修改systemd服务配置,阻止应用日志进入journal:
bash复制sudo nano /etc/systemd/system/your-service.service
将以下配置:
ini复制StandardOutput=journal
StandardError=journal
修改为:
ini复制StandardOutput=null
StandardError=null
然后重新加载并重启服务:
bash复制sudo systemctl daemon-reload
sudo systemctl restart your-service
sudo systemctl status your-service
4.2 配置合理的日志轮转
4.2.1 修正目录权限
bash复制sudo chmod 755 /var/log
sudo chown root:root /var/log
4.2.2 优化logrotate配置
编辑rsyslog的logrotate配置:
bash复制sudo nano /etc/logrotate.d/rsyslog
关键修改点:
- 删除所有
su syslog adm配置 - 为syslog添加size限制
- 设置合理的轮转数量
示例配置:
ini复制/var/log/syslog
{
rotate 3
size 50M
missingok
notifempty
delaycompress
compress
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
/var/log/mail.info
/var/log/mail.warn
[...其他日志文件...]
{
rotate 4
weekly
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
4.2.3 测试并应用配置
bash复制sudo logrotate -f /etc/logrotate.d/rsyslog
5. 应用层优化建议
5.1 Logback配置调整
在生产环境中,建议禁用控制台输出,只保留文件输出:
xml复制<springProfile name="!dev">
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</springProfile>
5.2 日志文件管理
配置合理的日志滚动策略:
xml复制<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>7</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
[...]
</appender>
6. 验证与监控
6.1 验证logrotate定时任务
bash复制ls /etc/cron.daily/logrotate
systemctl status logrotate.timer
6.2 监控磁盘使用情况
bash复制# 实时监控
watch -n 60 df -h /
# 历史趋势
cat /var/log/syslog | grep logrotate
6.3 设置告警规则
在云监控平台设置以下告警:
- 磁盘使用率 > 80%
- 持续IO负载 > 5MB/s
- 单个日志文件 > 100M
7. 经验总结与避坑指南
7.1 关键教训
- 不要忽视系统日志:syslog等系统日志可能成为"沉默的杀手"
- 双重确认日志配置:应用日志框架和系统服务配置需要协同检查
- 权限问题要前置处理:特别是涉及多用户访问的目录
7.2 常见问题排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| logrotate报权限错误 | /var/log目录权限问题 | chmod 755 /var/log |
| syslog仍然快速增长 | systemd服务未正确修改 | 确认StandardOutput=null |
| 轮转后日志丢失 | postrotate脚本未执行 | 检查rsyslog-rotate是否存在 |
| 磁盘IO持续高位 | 日志压缩耗时 | 调整compress参数或升级硬件 |
7.3 推荐的最佳实践
- 生产环境禁用控制台日志:避免日志重复输出
- 设置合理的日志级别:生产环境建议WARN级别起步
- 实现多维度监控:磁盘空间、IO负载、日志文件大小三位一体
- 定期演练应急预案:模拟磁盘满场景下的处理流程
通过这次事件,我深刻认识到系统日志管理的重要性。现在,我会在每个新服务部署时都检查这些配置,确保不会重蹈覆辙。对于运维同学来说,预防永远比救火更重要。