# Syslog消息格式:RFC 5424 vs RFC 3164

Syslog与Filebeat日志采集平台搭建及存储设计 - 第3节

理解Syslog的两套“方言”

说起Syslog的消息格式,其实有两个标准在打架。老的是RFC 3164,新的是RFC 5424。我刚开始接触日志系统时,也被这两个格式搞晕过——明明都叫Syslog,解析起来却完全不一样。

说白了,RFC 3164是“野路子”出身。它更像一个约定俗成的格式,大家照着做就行。而RFC 5424是IETF后来正式制定的标准,结构清晰,扩展性强。

你想想看,如果日志格式都不统一,分析工具怎么工作?我在一个项目中就吃过这个亏。当时用Filebeat收集网络设备日志,结果一半能解析,一半直接报错。后来才发现,老设备走的是RFC 3164,新设备用的是RFC 5424。

RFC 3164——传统格式

RFC 3164最早在2001年发布。它的格式很简单,甚至有点简陋。

<PRI>Timestamp Hostname Message

一个典型的RFC 3164消息长这样:

<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8

我来拆解一下各部分:

  • <34> —— PRI值,由Facility和Severity计算得出。公式是:PRI = Facility × 8 + Severity。
  • Oct 11 22:14:15 —— 时间戳。不带年份,格式固定。嗯,这里要小心——没有年份信息,跨年日志处理起来会很头疼。
  • mymachine —— 主机名。可以是短名称,也可以是FQDN。
  • su: 'su root' failed for lonvick on /dev/pts/8 —— 消息体。剩下的全是内容,没有结构化字段。

我曾经遇到过的一个坑:RFC 3164的时间戳没有时区信息。如果你的设备分布在多个时区,时间对齐就会非常麻烦。我有个客户,美国的防火墙和中国的服务器混在一起,日志时间全靠猜。后来我建议统一用NTP对齐到UTC,才解决了这个问题。

RFC 5424——现代化格式

RFC 5424在2009年发布。它解决了老格式的诸多痛点。我个人习惯,只要条件允许,都会优先用这个格式。

一个完整的RFC 5424消息长这样:

<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] BOMAn application event log entry...

看着比老格式复杂多了吧?其实结构更清晰:

  • <165> —— PRI值,和RFC 3164一样计算。
  • 1 —— 版本号。固定为1,用于标识这是RFC 5424格式。
  • 2003-10-11T22:14:15.003Z —— 时间戳。带时区、带毫秒,格式为ISO 8601。
  • mymachine.example.com —— 主机名。必须是FQDN。
  • evntslog —— 应用名称。用于标识产生日志的进程。
  • - —— 进程ID。这里用“-”表示没有提供。
  • ID47 —— 消息ID。可以用于关联同一类型的日志。
  • [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] —— STRUCTURED-DATA。这是新格式最牛的扩展点,可以携带键值对。
  • BOMAn application event log entry... —— MSG。消息体,前缀BOM用于标识UTF-8编码。

RFC 5424的STRUCTURED-DATA部分,说白了就是一组标准化的键值对。你可以在里面放任何自定义字段,比如请求ID、用户ID、业务类型。解析器拿到后可以直接提取,不用再做正则匹配。

核心差异对比

我整理了一张表,两套格式的核心区别一目了然:

特性 RFC 3164 RFC 5424
发布时间 2001年 2009年
版本号 无 固定为1
时间戳格式 Mmm dd hh:mm:ss ISO 8601,含时区和毫秒
年份信息 无 完整4位年份
时区信息 无 包含
主机名 可短可长 强制FQDN
结构化数据 不支持 支持SD-ID和键值对
字符编码 无明确约定 UTF-8
消息长度 通常不超过1024字节 支持更长,可协商

为什么两个格式共存?

这不是技术问题,而是历史包袱问题。市面上大量网络设备、防火墙、老服务器还在跑RFC 3164。要它们升级固件支持新格式,成本太高。

我记得在给一家金融公司做日志方案时,他们的核心交换机就是RFC 3164的忠实用户。没办法,只能让Filebeat同时兼容两种格式。

实际项目中如何选择?

我的建议很直接:

  • 新建系统:强制用RFC 5424。前期规范一点,后期省事很多。
  • 老系统改造:如果可以升级软件,就升级。不行就继续用老格式,用解析器做兼容。
  • 混合场景:用Filebeat或Rsyslog做格式统一。Filebeat可以在输入端自动识别PRI和版本号,判断走哪种解析逻辑。

关键经验:我曾经帮客户排查过一个诡异问题。他们的日志分析平台突然少了一半数据,查了两天才发现,某台服务器的Syslog从4.3升级到了5.0,默认输出的格式从3164变成了5424。解析器只支持老格式,新格式的日志全部被丢弃了。从那以后,我养成了一个习惯——在日志采集层做格式检测和报警,而不是默认信任所有输入。

SVG:Syslog消息格式演化流程图

下面这张图展示了从RFC 3164到RFC 5424的演化路径,以及现代应用中最常见的适配方案:

Syslog消息格式演化与适配策略 RFC 3164 传统格式 无版本号 · 无时区 无结构化数据 RFC 5424 现代格式 版本号 · ISO 8601时间戳 STRUCTURED-DATA扩展 标准化升级 解析困难 · 时间错乱 跨设备/跨时区兼容性差 面临问题 Filebeat统一采集 自动识别格式 · 兼容适配 方案A:保持老格式 适用老旧设备 方案B:升级新格式 新建系统强制采用 建议:统一使用Filebeat输入端进行格式归一化处理,确保下游分析平台无感知

Filebeat中的配置实战

在Filebeat中处理两种格式,其实很简单。Filebeat会自动识别PRI值和版本号字段,不需要人工干预。但我建议你显式配置一下,确保兼容性。

filebeat.inputs:
- type: syslog
  protocol.udp:
    host: "0.0.0.0:514"
  # 自动兼容两套格式
  # RFC 3164 和 RFC 5424 都能解析
  fields_under_root: true
  fields:
    log_type: syslog

嗯,这里要注意。Filebeat默认的syslog输入支持两种格式,但如果你需要从结构化数据中提取字段,就得加上自定义配置了:

processors:
  - dissect:
      tokenizer: "%{facility_severity} %{timestamp} %{hostname} %{process}: %{message}"
      field: "message"
      target_prefix: "parsed"

我个人习惯在测试环境先用一条真实日志验证解析结果。这是最稳妥的办法,别问我怎么知道的——我踩过太多坑了。

测试解析的命令:echo '<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - - BOMfailure' | nc -u localhost 514。发过去后,去Filebeat的日志里看字段是否完整。

最后说一句,两种格式的选择,本质上是兼容性和扩展性的权衡。如果你的日志需要被多种系统消费,RFC 5424是更安全的选择。如果只是内部简单使用,RFC 3164也够用。关键是要搞清楚你的设备支持什么,以及你的下游系统能解析什么。