我一直在关注RFC5424找到将结束系统日志事件的正式指定的标记。
不幸的是我找不到它。所以如果我想实现一些对某些消息做出反应的小型系统日志服务器,那么结束消息的标记是什么(是的,通常事件是一行,但我在规范中找不到它)
澄清:
我之所以称之为事件,是因为我将一条消息与一行关联起来。事件可能是这样的
Type: foo
Source: webservers
而给我的消息是这样的:
Type: foo Source: webservers
https://www.rfc-editor.org/rfc/rfc5424#section-6定义:
SYSLOG-MSG = HEADER SP STRUCTURED-DATA [SP MSG]
既不STRUCTURED-DATA
告诉MSG
我这些字段如何结束。特别MSG
是被定义为,MSG-ANY / MSG-UTF8
它几乎可以扩展到任何东西。没有任何东西说换行符标志着结束(或者就此而言8
或a
)。给出示例消息(第 6.5 节):
这是一个有效消息或两个有效消息,具体取决于您是否表示某个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?
\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?
\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?
要么是我误读了 RFC,要么就是没有提及。RFC 中指定的尺寸只是说明了我可以使用的最小长度……
回答?:显然我读错了 RFC。需要查看具体的传输 RFC 并遵守该 RFChttps://www.rfc-editor.org/rfc/rfc5426#section-3.1以上就是 UDP 传输的全部内容。
@joechip:由于你的评论和答案引导我实际阅读更多关于传输 RFC 的内容,如果您朝这个方向稍微更新一下,我会很乐意接受您的答案:)
答案1
那么,您所说的“系统日志事件”是什么意思呢?如果您指的是系统日志消息,那么 RFC5424 在第 6 节中明确定义了系统日志消息语法,即如何将其从一个系统日志应用程序传输到另一个系统日志应用程序。
如果您指的是接收系统日志应用程序如何将它们存储在日志文件中,典型的系统日志实现只是用换行符将一条记录与另一条记录分开,这通常不是可配置的行为。此外,系统日志记录的文本字段也可以包含换行符,这会使正确解析日志文件的任务变得复杂。尽管如此,它通常可以解析,因为每个系统日志记录都以通常的日期、时间、主机和标签序列开头,而系统日志记录中的换行符通常不会跟有类似的文本。
我认为更改 syslog 存储记录分隔符的功能将是一个有用的功能,但记录本身中出现的任何此类分隔符都应被转义,以便它有用。向纯文本文件添加如此多的结构必然是一种妥协。如果您非常关心这个问题,也许您应该支持以某种定义明确的二进制格式写入日志文件(例如,sqlite 在这里可能很有用)。
编辑:仔细检查 RFC5424 第 6 节后发现,系统日志消息可以有两种形式:
HEADER SP STRUCTURED-DATA
或者
HEADER SP STRUCTURED-DATA SP MSG
通过扩展 ABNF 规范,我们很容易发现第一种形式以“-”或“]”结尾。在这个最后一个字符之前可能还有其他“-”和“]”字符,因此不能将其视为 syslog 消息终止符。
第二种形式的结尾取决于 MSG 的结尾方式。MSG 可以是 UTF-8 字符串(如 RFC 3629 中所述,不包含字符串终止符),也可以是任意以任意值结尾的八位字节流。显然,这种形式也没有指定这样的终止符号。
但事实上,无论采用何种形式,都不需要 syslog 消息终止符,因为消息长度由传输层带外传递。当应用程序发送 UDP 数据包时,syslog 消息必须已根据规范准备好并存储在缓冲区中。应用程序将此缓冲区传递给函数或方法以发送它,并且要发送的字节数也会传递。例如,在 C 中我们有:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
在此示例中,长度是应该从缓冲区中获取的字节数缓冲区并发送到远程主机。
同样,在系统日志服务器上调用另一个函数或方法,例如这个:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
此函数返回缓冲区中接收的 UDP 有效负载的长度(以字节为单位)缓冲区。如果应用程序尝试读取超过此返回长度的数据,则会出现垃圾数据(或分段错误)。为了避免读取超过此限制的数据,通常会在位置处放置一个 NULL 值缓冲区[大小]就在siz=接收自(…)调用。这样,任何后续函数调用使用缓冲区作为字符串将正常工作。当然,此空终止仅适用于字符串,而不适用于八位字节流。正如我所说,此空值通常不会通过网络传输,而仅由接收应用程序添加。
对于作为接收应用程序的系统日志服务器来说,大多数系统日志服务器可能会添加这个空终止符以便在内部处理接收的字符串(如果它们将其视为字符串的话),但是在任何情况下,当将字符串附加到日志文件时,都会省略这个空值,以免破坏整个日志文件的文本处理。
答案2
在第 6.1 节中,他们定义了消息长度。我认为,当您获得完整的消息时,您将拥有标头和数据,并且它们加起来就是该长度。
除此之外,我看不到其中有任何用于多条消息的功能。所以我认为每条消息都是一个事件。没有任何形式的多条消息跟踪,也没有为开始、中间和结束消息指定编码。Syslog 跟踪已记录的消息,它实际上没有更高级别的事件概念。