系统日志事件的正式分离标记?

Mar*_* M. 7 syslog protocol rfc

我一直在查看RFC5424以找到将结束系统日志事件的正式指定标记。

不幸的是我找不到它。因此,如果我想实现一些对某些消息做出反应的小型系统日志服务器,那么结束消息的标记是什么(是的,通常事件是一行,但我在规范中找不到它)

澄清

我称之为事件是因为我将一条消息与一行相关联。一个事件可能是这样的

Type: foo
Source: webservers
Run Code Online (Sandbox Code Playgroud)

而给我的信息是这样的:

Type: foo Source: webservers
Run Code Online (Sandbox Code Playgroud)

http://tools.ietf.org/html/rfc5424#section-6定义:

SYSLOG-MSG      = HEADER SP STRUCTURED-DATA [SP MSG]
Run Code Online (Sandbox Code Playgroud)

既不STRUCTURED-DATA也不MSG告诉我这些领域如何结束。特别MSG是被定义为MSG-ANY / MSG-UTF8几乎可以扩展到任何东西。没有什么说换行符标志着结束(或 an8或 ana就此而言)。鉴于示例消息(第 6.5 节):

这是一条有效消息,或 2 条有效消息,具体取决于您是否说HEADER元素绝不能出现在任何MSG元素中:

文字空白

<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - <34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47
                                                                |
                                                               is this an end marker?
Run Code Online (Sandbox Code Playgroud)

\t 代表一个选项卡

<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 -\t<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47
                                                                |
                                                               is this an end marker?
Run Code Online (Sandbox Code Playgroud)

\n 代表换行

<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 -\n<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47
                                                                |
                                                               is this an end marker?
Run Code Online (Sandbox Code Playgroud)

要么我误读了 RFC,要么根本没有提及。RFC 中指定的尺寸只是说明了我可以使用的最小长度...

回答?: 显然我读错了 RFC。人们需要去特定的传输 RFC 并保持http://tools.ietf.org/html/rfc5426#section-3.1为 UDP 传输说明一切。

@joechip:由于您的评论和回答使我实际上在传输 RFC 中阅读了更多内容,如果您朝那个方向稍作更新,我将很乐意接受您的回答:)

joe*_*hip 2

那么,“系统日志事件”是什么意思?如果您引用系统日志消息,RFC5424 在其第 6 节中明确定义了系统日志消息语法,以及如何将其从一个系统日志应用程序传输到另一个系统日志应用程序。

如果您指的是接收系统日志应用程序如何将它们存储在日志文件中,典型的系统日志实现只是使用换行符将一条记录与另一条记录分开,这通常不是可配置的行为。此外,系统日志记录的文本字段还可以包含换行符,这使正确解析日志文件的任务变得复杂。尽管如此,它通常还是可以被解析的,因为每个系统日志记录都以通常的日期、时间、主机和标签序列开头,而系统日志记录中的换行符后面通常不会跟有类似的文本。

我认为更改系统日志存储记录分隔符的能力将是一个有用的功能,但是记录本身内出现的任何此类分隔符都应该被转义,这样才有用。向纯文本文件添加如此多的结构必然是一种妥协。如果您非常关心这个问题,也许您应该支持以某种定义明确的二进制格式写入日志文件(例如,sqlite 在这里可能很有用)。

编辑:对 RFC5424 第 6 节进行更仔细的检查表明,系统日志消息可以有两种形式:

HEADER SP STRUCTURED-DATA
Run Code Online (Sandbox Code Playgroud)

或者

HEADER SP STRUCTURED-DATA SP MSG
Run Code Online (Sandbox Code Playgroud)

通过扩展ABNF规范,我们可以很容易地看到第一种形式以“-”或“]”结尾。在最后一个字符之前可能还有其他“-”和“]”字符,因此不能将其视为系统日志消息终止符。

第二种形式的结尾取决于 MSG 的结尾方式。MSG 可以是 UTF-8 字符串(如 RFC 3629 中指定,不包含字符串终止符)或以任何值结尾的任意八位字节流。显然,这种形式也没有指定这样的终止符号。

但事实是,无论系统日志消息采用什么形式,都不需要系统日志消息终止符,因为消息长度是由传输层在带外传递的。当应用程序发送 UDP 数据包时,系统日志消息必须已根据规范准备好并存储在缓冲区中。应用程序将此缓冲区传递给函数或方法以便发送它,并且还要传递要发送的字节数。例如,在 C 中我们有:

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);
Run Code Online (Sandbox Code Playgroud)

在此示例中,len是应从缓冲区buf中取出并发送到远程主机的字节数。

同样,在系统日志服务器上调用另一个函数或方法,例如:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
Run Code Online (Sandbox Code Playgroud)

此函数返回缓冲区buf中接收的 UDP 有效负载的长度(以字节为单位)。如果应用程序尝试读取超过此返回长度的数据,则会出现垃圾(或分段错误)。为了避免读取超出此限制,通常在siz=recvfrom(...)调用之后在位置buf[siz]处放置一个 NULL 值。这样,任何以后使用buf作为字符串的函数调用都将正常工作。当然,这种空终止仅适用于字符串,不适用于八位字节流。正如我所说,这个空值通常不会通过网络传输,而是仅由接收应用程序添加。

在系统日志服务器作为接收应用程序的情况下,大多数系统日志服务器可能会添加此空终止以用于接收字符串的内部处理(如果它们将其视为字符串),但在任何情况下都会保留此空值当字符串附加到日志文件时,以免中断整个日志文件的文本处理。