在生产环境中,日志远程同步就不要再使用 UDP 了,原因非常明确:一旦发生丢包,通常还是静默丢失,后续排查会十分被动。更稳定、更适合线上场景的方案是使用 TCP。落实到 rsyslog 配置时,必须显式加载 imtcp 模块,并通过 input 监听 514 端口;客户端在编写日志转发规则时,也一定要使用 @@,不能误写成 @。此外,队列参数、SELinux 布尔值,以及基于 %FROMHOST-IP% 的模板配置,也需要同时完善,这几个关键项少了任何一个,整套 Linux 日志远程同步方案都很难长期稳定运行。

生产环境下进行日志同步,建议必须使用 TCP 协议。因为 UDP 很容易出现静默丢包,排查故障时往往连日志是否成功传输都无法确认。
服务端监听 514 端口时必须显式启用 imtcp 模块
首先要明确一点:rsyslog 默认不会主动监听任何网络端口,所以仅仅知道配置思路还不够,若不真正启用模块和输入配置,实际并不会生效。需要在 /etc/rsyslog.conf 或 /etc/rsyslog.d/ 目录中的任意配置文件里,先加载对应模块,再明确声明日志输入源。
- 取消注释或新增
module(load="imtcp") - 随后添加
input(type="imtcp" port="514")(注意括号和引号都不能遗漏) - 如果只加载了模块,却没有写
input这一行,那么执行ss -tnl | grep 514时看不到监听端口,而systemctl restart rsyslog也通常不会报错——这正是最容易被忽视的关键步骤 - UDP 的配置方式同样类似:需要
module(load="imudp")+input(type="imudp" port="514"),但在正式生产环境中并不推荐使用
客户端日志转发规则必须写 @@,不能写成 @
@ 表示 UDP,只有 @@ 才表示 TCP。很多 rsyslog 日志转发失败的问题,根源往往只是抄配置时少写了一个字符:
- 错误写法:
*.* @192.168.1.100:514→ 日志发出后可能直接丢失,服务端也收不到,使用tcpdump -nn port 514抓包时甚至看不到 TCP 流量 - 正确写法:
*.* @@192.168.1.100:514;RSYSLOG_ForwardFormat→ 分号后补上格式模板,可避免时间戳或主机名等关键信息缺失 - 还必须补充队列参数,否则在网络抖动或短暂中断时,日志很可能直接丢失:
$ActionQueueFileName fwdRule1、$ActionQueueMaxDiskSpace 1g、$ActionQueueSa veOnShutdown on - 如果系统启用了 SELinux,则需要执行
setsebool -P rsyslog_forward on,否则 rsyslog 的转发连接可能会被静默拒绝
日志按来源 IP 分类存储时必须使用 %FROMHOST-IP% 模板
如果使用 %HOSTNAME% 作为分类依据并不可靠——因为主机名可能被伪造、重复,或者解析失败;而 %FROMHOST-IP% 才更能准确标识日志真实来源,适合 Linux 服务器日志集中存储场景:
- 定义模板:
$template RemoteLogs,"/var/log/remote/%FROMHOST-IP%/%PROGRAMNAME%.log" - 应用规则:
*.* ?RemoteLogs(注意这里使用的是问号,不是分号) - 目标目录需要提前创建并设置权限:
mkdir -p /var/log/remote/192.168.1.5+chown syslog:adm /var/log/remote/192.168.1.5 - 如果模板路径中包含非法字符(例如冒号、斜杠),rsyslog 会静默跳过写入,这时可以通过
journalctl -u rsyslog -f看到invalid template相关提示
真正困难的地方,不只是把几行 rsyslog 配置写对,而是要确认每一层链路都已经打通:客户端必须能够连接 514 端口(nc -vz 192.168.1.100 514),服务端要能通过 ss 看到监听状态,tcpdump 能抓到实际传输的数据包,目录权限要正确,模板变量也不能为空。只要其中任意一环出问题,远程日志就可能卡在传输链路中间,最终导致 Linux 日志同步失败。
