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 在此层有显著差异。
常见陷阱: 很多运维人员只配置了 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 | 邮件系统 | 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,建议逐步迁移到 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 传输以保证可靠性。