日志重复记录源于 rsyslog 默认无排他性过滤,导致匹配多条规则时重复写入;解决需在 messages 规则前加 !local0.* 排除、禁用 journal-to-syslog 二次采集、远程日志用模板或 facility 隔离,并通过 logger 测试与调试验证。

日志重复记录是 Syslog 配置中最常见的干扰项之一,尤其在启用远程接收或自定义 facility 后,同一份日志可能同时出现在 /var/log/messages、指定业务日志文件(如 /var/log/web/access.log)甚至 /var/log/cron 中。根本原因不是服务冲突,而是 rsyslog 的默认规则未做排他性过滤——它会把匹配的每条日志,按顺序逐条写入所有符合条件的目标。
明确日志流向,避免规则重叠
rsyslog 按配置文件中规则出现的顺序逐行匹配,一旦某条日志满足某条规则,就会被写入对应目标;若后续规则也匹配,仍会继续写入。比如:
-
local0.* -/var/log/web/access.log→ 把所有 local0 日志写入 web 日志 -
*.info;mail.none;authpriv.none;cron.none /var/log/messages→ 默认也包含 local0.info 级别,因此同样写入 messages
解决方法是在 messages 规则前加排除条件:!local0.*;*.info;mail.none;authpriv.none;cron.none /var/log/messages
开头的 ! 表示“不匹配 local0 的任何级别”,这样 local0 日志就只进指定文件,不再进 messages。
关闭本地日志冗余输出
某些 rsyslog 版本(尤其是较新发行版)默认启用了 journal-to-syslog 转发,导致 systemd-journald 已记录的日志又被 rsyslog 二次采集,造成 cron、kernel 等日志重复。
- 检查
/etc/rsyslog.conf是否有$OmitLocalLogging on(已启用) - 确认
$IMJournalStateFile行未被注释(即保留$IMJournalStateFile imjournal.state) - 禁用
imklog模块(如第11行# $ModLoad imklog应保持注释状态),避免内核日志被重复加载
改完后重启: systemctl restart rsyslog
远程日志接收时隔离本地与远程来源
开启 -r 参数接收远程日志后,若不区分来源,远程设备发来的 local0 日志和本机应用写的 local0 日志将混在一起处理,容易误触发重复规则。
- 在 rsyslog 配置中,使用模板 + 属性判断区分来源:
$template RemoteWeb,"/var/log/remote/web/%FROMHOST-IP%.log":fromhost-ip, !isequal, "127.0.0.1" ?RemoteWeb - 或更稳妥地,为远程日志单独分配 facility(如 remote-local0),再通过
if $syslogfacility-text == 'remote-local0'做精确路由
这样既能集中存储,又不会和本机日志路径冲突。
验证与调试技巧
不要仅靠重启后看文件内容判断是否生效,容易遗漏中间缓存或延迟写入:
- 用
logger -p local0.info "test msg"手动触发一条测试日志,立刻检查目标文件和 messages 是否只出现一次 - 启用 rsyslog 调试模式:
rsyslogd -dn 2>/tmp/rsyslog-debug.log,观察日志匹配路径 - 检查日志权限和 SELinux 上下文(如
restorecon -Rv /var/log),避免因写入失败导致 syslog 尝试降级写入其他路径
不复杂但容易忽略。










