问题背景
生产环境一台核心日志服务器(CentOS 7 + rsyslog 8.24)在 2026-09-18 凌晨开始出现磁盘空间告警,/var/log 分区在 4 小时内从 38% 涨到 87%。该服务器承担全网 200+ 台设备(交换机、防火墙、Linux 服务器、Windows 事件转发)的集中日志收集,日常写入量约 1.2GB/天。监控显示 /var/log/messages 单文件在 3 小时内从 180MB 暴增到 2.1GB,且持续高速写入。
故障现象
- 磁盘空间异常:
df -h显示/var/log持续增长,du -sh /var/log/messages与ls -lh显示文件大小每分钟增加 8-12MB。 - 日志内容重复:
tail -f /var/log/messages发现同一条 SSH 登录事件、cron 执行记录每隔 1-2 秒出现两次,时间戳完全一致。 - journald 回压:
systemctl status systemd-journald显示Storage=auto下RuntimeJournal持续增长,journalctl --disk-usage报告 4.2GB,且journalctl -f输出明显滞后。 - 无明显错误日志:rsyslog 本身未报错,
/var/log/rsyslog.log仅记录正常启动与 HUP 重载。
排查过程
第一步:定位写入源
|
|
发现两个 rsyslog 进程(PID 1247、1248)同时持有该文件句柄,且两个进程的打开文件描述符指向同一 inode。这表明 rsyslog 内部存在两个独立的写入动作。
第二步:检查 rsyslog 配置
|
|
未报错。进一步检查 /etc/rsyslog.d/ 下的自定义配置:
|
|
关键片段:
|
|
这里同时存在两种写入方式:
- 显式的
action(type="omfile")模块调用,指定了template - 传统的
selector + file语法*.info;... /var/log/messages
传统语法会隐式使用全局 $template(或默认 RSYSLOG_TraditionalFileFormat),而 action 模块又显式指定了另一个模板。两者同时生效,导致同一条日志被写入两次。
第三步:验证重复写入根因
|
|
确认全局 $template CustomMsgFormat 定义在 /etc/rsyslog.conf 第 87 行,而 99-custom.conf 里又定义了同名模板并在 action 中引用。rsyslogd 解析时,后加载的 99-custom.conf 覆盖了全局模板,但传统 selector 行仍使用默认模板,两者并行写入。
第四步:确认磁盘增长与 journald 关系
|
|
发现 journald 本身也在记录大量重复的 rsyslog 启动/重载事件(因为 rsyslog 不断触发 HUP),形成正反馈循环:日志重复写入 → journald 刷盘 → 触发 rsyslog 自身日志 → 再次重复。
解决方案
立即止血(热修复)
|
|
根治配置
编辑 /etc/rsyslog.d/99-custom.conf,删除传统 selector 行,只保留 action 模块:
|
|
同时在 /etc/rsyslog.conf 全局段添加:
|
|
重载验证
|
|
检查 tail -f /var/log/messages,确认同一事件不再重复出现。
根因分析
rsyslog 支持两种配置语法共存:
- 传统 selector + 文件路径:隐式使用全局
$template或默认RSYSLOG_TraditionalFileFormat - action(type=“omfile”) 模块:显式指定
template参数
当两者同时指向同一文件,且模板名称或内容不同时,rsyslog 会为每个匹配的 rule 创建独立的输出动作,导致日志被多次写入。本次事故的直接诱因是「自定义 action 模块与传统 selector 同时存在,且未统一模板」。
预防措施
- 配置规范化:全站 rsyslog 配置统一改用
action(type="omfile")模块语法,彻底弃用传统 selector + 文件路径写法。 - 模板集中管理:所有自定义模板放在
/etc/rsyslog.d/00-templates.conf,并在rsyslog.conf顶部include;各业务配置仅引用模板名,不重复定义。 - 配置审查脚本:在 CI/CD 流水线中加入 rsyslog 配置 lint(检查是否同时存在传统 selector 与 action 模块指向同一文件)。
- 监控增强:
- 新增
rsyslog进程打开文件数监控(lsof | grep rsyslog | wc -l) /var/log目录 inode 使用率监控(df -i)- journald 磁盘使用率告警阈值从 80% 提前到 60%
- 新增
- 日志轮转策略收紧:
logrotate配置中增加size 100M触发条件,配合copytruncate避免 rsyslog 句柄失效。
总结
一次看似「日志模板自定义」的细微配置差异,在 rsyslog 双语法共存的场景下演变为磁盘空间危机与 journald 回压。本次排查再次印证:日志系统配置必须「单一事实来源」,传统 selector 与 action 模块不可混用指向同一目标文件。后续将把 rsyslog 配置统一收敛到模块化语法,并纳入变更前 lint 门禁,避免同类问题复发。