1. syslog 协议基础:RFC 3164 与 RFC 5424 的演进与核心概念

syslog 是 Unix/Linux 系统中最核心的日志传输协议,也是内核日志、系统服务日志、网络设备日志远程收集的事实标准。理解 syslog 协议的发展历史、层级结构以及 facility/severity 定义,是后续配置 rsyslog、syslog-ng 以及排查远程日志丢失、格式错乱、性能瓶颈的基石。

1.1 发展历史:从 BSD 到 IETF 标准化

阶段 时间 关键事件 协议版本
起源 1980s Eric Allman 在 Sendmail 中实现 syslog,随 4.2 BSD 发布 无正式 RFC
事实标准 2001 IETF 发布 RFC 3164,将 BSD syslog 格式文档化 RFC 3164
结构化演进 2009 IETF 发布 RFC 5424,引入结构化数据、可靠传输、国际化支持 RFC 5424
当前生态 至今 rsyslog、syslog-ng 同时支持 RFC 3164 和 RFC 5424;新部署推荐 RFC 5424 双协议栈
运维要点: 生产环境中,老旧设备(如网络交换机、嵌入式系统)通常只支持 RFC 3164;而 Linux 发行版(RHEL 8+/Ubuntu 18.04+)的 rsyslog 默认输出 RFC 5424 格式。远程收集时,接收端必须同时兼容两种协议,否则会导致日志解析失败或字段丢失。

1.2 协议层级结构:传输层与消息层

syslog 协议在逻辑上分为两层:传输层(如何发送)和消息层(发送什么)。

  • 传输层:定义 syslog 消息如何从发送端到达接收端。常见传输方式包括 UDP(默认,端口 514)、TCP(端口 601 或 6514)、TLS(加密传输,端口 6514)。
  • 消息层:定义 syslog 消息的格式和字段结构。RFC 3164 和 RFC 5424 在此层有显著差异。
syslog 协议层级结构 传输层(Transport Layer) UDP 514(默认,无连接) | TCP 601(可靠) | TLS 6514(加密) RELP(rsyslog 增强可靠协议)| 消息队列(Kafka/AMQP) 消息层(Message Layer) RFC 3164(传统格式) <PRI>TIMESTAMP HOSTNAME MSG 无结构化数据,长度限制 1024 字节 RFC 5424(结构化格式) <PRI>VERSION TIMESTAMP HOSTNAME APP-NAME PROCID MSGID STRUCTURED-DATA MSG
常见陷阱: 很多运维人员只配置了 UDP 514 端口,但 UDP 传输存在最大消息长度限制(RFC 3164 为 1024 字节,RFC 5424 为 2048 字节),且无确认机制。当内核日志量突增(如 OOM、磁盘故障)时,UDP 丢包率可能超过 30%。生产环境建议至少启用 TCP 传输,关键场景使用 RELP 或 TLS。

1.3 Facility 与 Severity 定义

每个 syslog 消息都包含一个 优先级值(Priority Value, PRI),由 facility × 8 + severity 计算得出。接收端根据 PRI 值决定日志的路由、存储和告警策略。

1.3.1 Facility(设备/功能代码)

Facility 标识日志的来源子系统。RFC 5424 扩展了 RFC 3164 的 facility 范围,新增了 local0–local7 的明确用途建议。

代码 关键字 描述 典型来源
0 kern 内核消息 kernel, dmesg
1 user 用户级消息 用户进程
2 mail 邮件系统 postfix, sendmail
3 daemon 系统守护进程 sshd, crond
4 auth 安全/认证消息 login, sudo
5 syslog syslog 内部消息 rsyslogd 自身日志
6 lpr 行式打印系统 cups, lpd
7 news 网络新闻组 INN
8 uucp UUCP 子系统 uucico
9 cron 计划任务 crond, atd
10 authpriv 安全/认证消息(私有) sshd, pam
11 ftp FTP 守护进程 vsftpd, proftpd
16–23 local0–local7 本地自定义使用 应用程序、容器、网络设备

1.3.2 Severity(严重级别)

Severity 标识日志的紧急程度。数值越小,优先级越高。

代码 关键字 描述 典型触发场景
0 emerg 系统不可用(紧急) 内核 panic、系统崩溃
1 alert 必须立即处理 磁盘损坏、内存耗尽
2 crit 严重错误 硬件故障、文件系统错误
3 err 一般错误 服务启动失败、配置错误
4 warning 警告 磁盘空间不足、连接超时
5 notice 正常但重要 服务重启、用户登录
6 info 信息性消息 请求处理、状态更新
7 debug 调试信息 开发/排错时启用

1.3.3 PRI 计算示例

内核发出的紧急消息:facility=0 (kern),severity=0 (emerg),则 PRI = 0 × 8 + 0 = 0,消息头部为 <0>。

local0 发出的警告消息:facility=16 (local0),severity=4 (warning),则 PRI = 16 × 8 + 4 = 132,消息头部为 <132>。

# 查看当前系统日志的 facility/severity 映射
grep -E 'kern\.|user\.|daemon\.|auth\.|local[0-7]\.' /etc/rsyslog.conf

# 手动构造一条测试 syslog 消息(facility=local0, severity=warning)
logger -p local0.warning "这是一条测试警告消息"
内核日志特别说明: 内核日志(kern facility)在 Linux 中通过 printk() 函数输出,其日志级别与 syslog severity 一一对应。例如 KERN_EMERG 对应 severity 0,KERN_ERR 对应 severity 3。内核日志首先写入 /dev/kmsg,然后由 rsyslog 的 imklog 模块读取并转发到 syslog 管道。

1.4 RFC 3164 与 RFC 5424 消息格式对比

字段 RFC 3164 RFC 5424
PRI <PRI>(必需) <PRI>(必需)
版本 无 VERSION(必需,当前为 1)
时间戳 Mmm dd hh:mm:ss(本地时间,无年份) ISO 8601(YYYY-MM-DDThh:mm:ss.µs±hh:mm)
主机名 HOSTNAME(可选,常为短主机名) HOSTNAME(FQDN 或 IP,必需)
应用名 包含在 MSG 中,无独立字段 APP-NAME(独立字段)
进程 ID 包含在 MSG 中 PROCID(独立字段)
消息 ID 无 MSGID(用于标识消息类型)
结构化数据 无 STRUCTURED-DATA([key="value"] 格式)
消息体 MSG(BOM + 自由文本) MSG(UTF-8 编码,BOM 可选)
最大长度 1024 字节 2048 字节(可扩展)
RFC 3164 vs RFC 5424 消息格式对比 RFC 3164 示例 <34>Oct 11 22:14:15 myhost su[1234]: 'su root failed for user' PRI=34 (daemon.crit) | 时间戳无年份 | 主机名短格式 | 进程ID嵌入MSG RFC 5424 示例 <34>1 2025-10-11T22:14:15.003Z myhost.example.com su 1234 ID47 [exampleSDID@32473 iut="3" eventSource="Application"] 'su root failed for user' 版本1 | ISO 8601 时间戳 | FQDN 主机名 | 独立 APP-NAME/PROCID/MSGID | 结构化数据
迁移建议: 如果当前环境使用 RFC 3164,建议逐步迁移到 RFC 5424。迁移时注意:接收端需配置 $EscapeControlCharactersOnReceive off(rsyslog)以兼容旧格式;发送端需确认应用是否支持结构化数据注入。对于内核日志,RFC 5424 可以携带 @timestamp、@source_host 等结构化字段,极大方便了 Elasticsearch 等日志平台的索引和搜索。

1.5 本章小结

  • syslog 协议从 BSD 起源,经过 RFC 3164(传统)到 RFC 5424(结构化)的演进,当前处于双协议栈共存阶段。
  • 协议分为传输层(UDP/TCP/TLS/RELP)和消息层(PRI + 头部 + 消息体)。
  • Facility 标识来源(0=kern, 1=user, ..., 16-23=local0-7),Severity 标识紧急程度(0=emerg, 7=debug),PRI = facility × 8 + severity。
  • 内核日志使用 facility 0(kern),其日志级别与 syslog severity 完全对应,通过 printk() → /dev/kmsg → imklog 管道进入 syslog 系统。
  • 远程收集时,接收端必须同时兼容 RFC 3164 和 RFC 5424,并优先使用 TCP/TLS 传输以保证可靠性。