为什么 rsyslog 可能会记录来自 systemd 日志的重复消息?
我知道有关 systemd 日志损坏的已知问题(请参阅此处“目的”部分下的警告: https: //www.rsyslog.com/doc/configuration/modules/imjournal.html),但我不认为这是我遇到的问题。我正在运行 Ubuntu 24.04、rsyslog 8.2312.0-3ubuntu9 和 systemd 255.4-1ubuntu8.4。
我有多个主机运行名为“foobar”的应用程序作为 systemd 服务,并记录到 systemd 日志中。我还运行 rsyslog 作为 systemd 服务,它配置为将 JSON 格式的 foobar 日志从 systemd 日志转发到中央日志服务器。每个主机上的 rsyslog 配置如下:
module(load="imjournal" StateFile="journalState" IgnorePreviousMessages="on")
module(load="mmjsonparse")
template(name="foobarJSON" type="string" string="%TIMESTAMP% %HOSTNAME% %syslogtag% @cee: %$!all-json%\n" )
if $syslogfacility-text == "user" and $programname == "foobar" then {
user.* action(type="omfwd" target="central-logs.server" port="514" protocol="tcp" template="foobarJSON")
}
我还在中央日志服务器上将 rsyslog 作为 systemd 服务运行,并将来自每个服务器的 foobar 日志写入每个主机单独子目录内的本地文件。此主机上的 rsyslog 配置如下:
module(load="imtcp")
input(type="imtcp" address="123.456.789.0" port="514")
template(name="foobarHostLogs" type="string" string="/var/logs/%PROGRAMNAME%/%HOSTNAME%/%$year%/%$month%/%$day%.log")
module(load="builtin:omfile" DirCreateMode="0755")
if $fromhost-ip != '127.0.0.1' then {
action(type="omfile" dynaFile="foobarHostLogs")
& stop
}
在任何 foobar 主机上运行 journalctl -u foobar 时,我都看不到任何重复的消息。但是,在查看中央日志服务器上的日志文件时,我发现每条消息都是重复的:至少有一条消息仅包含来自 systemd 日志的“msg”字段(尽管有时我会看到两行相同的消息仅包含“msg”),紧接着是一行具有完全相同的时间戳和“msg”值以及来自 systemd 日志的所有其他元数据字段。
例如(我从下面的第二行删除了几个多余的字段,但希望您明白我的意思):
2024-09-15T00:00:00+00:00 host-a foobar[123456]: @cee: { "msg": "Hello, world!" }
2024-09-15T00:00:00+00:00 host-a foobar[123456]: @cee: { "_TRANSPORT": "journal", "_PID": "123456", "_UID": "1000", "_GID": "1000", "_COMM": "foobar", "_EXE": "\/usr\/local\/bin\/foobar", "_CMDLINE": ".\/foobar", "_CAP_EFFECTIVE": "0", "_SELINUX_CONTEXT": "unconfined\n", "MESSAGE": "Hello, world!", "msg": "Hello, world!" }
听起来你可能在客户端主机上配置了两种syslog 转发方法——除了通过 imjournal 读取日志(提供所有元数据)之外,它还可能通过 /run/systemd 中的 imuxsock 接收相同的日志(没有元数据的传统转发方法)。确保
ForwardToSyslog=
在你的 journald.conf 中禁用。好的,我能够弄明白。@u1686_grawity 是正确的,根本原因是 rsyslog 使用
imuxsock
和imjournal
输入模块从 systemd 日志读取消息,但简单地禁用并ForwardtoSyslog
不足以journald
阻止重复。相反,我必须通过将条件添加到原始 if 子句来配置 rsyslog 以仅将从
imjournal
中央日志服务器收到的消息转发,即:$inputname == "imjournal"
另外,我弄清楚了为什么我会收到这些空消息:我忘记实际调用
mmjsonparse
操作来解析结构化日志消息并从日志消息中获取所有单独的字段,所以我也将该行添加到上面的工作配置示例中。