i33*_*36_ 6 logs history syslog historical-unix systemd-journald
我最初想将其发布到 StackOverflow,因为我的兴趣主要来自于编程焦点,但在阅读了历史标签(以及它链接到的问题)后,我将其发布到 softwareengineering.se以深入了解实际/当前-日《软件工程》方面。然而,我的问题的根本历史性质是不可避免的,所以现在就到这里了。
\n我目前正在了解 Linux 上的日志记录如何工作,并且对RFC 5424或RFC 3164似乎未涵盖的实现细节有点困惑:用于将数据写入/dev/log
.
TL;DR:我正在尝试确定 a)“/dev/log
格式”的名称,以及 b)其语义的正式指定位置。我无法识别任何 RFC 或其他可引用的参考文献 - 仅代码实现特定规则,没有押韵或理由。
syslog()
虽然我最初对这个主题感兴趣,同时评估与其他日志记录策略(写入 stdout/stderr 和/或文件;发送到其他类型的日志服务器等)的优缺点,但有一次我意识到我完全无法确定“/dev/log
格式”如何/在何处适应更大的情况。关于 syslog 格式或协议的每个问题都讨论了 RFC,并且完全忽略了控制数据如何离开syslog()
并发送到 syslog 服务器的规则。
几乎就像 UNIX 的这个特定角落已经完全消失在木制品中一样,就像不再存在一样……而每天都有数万亿条日志消息使用这种“格式”(?)写入。
\n因此,这个问题是试图消除这个特定细节的歧义,只是为了这样做,描述格式,并确定可引用的参考文献。
\n日志行似乎需要以非常特定的方式进行格式化才能被接受(在我的例子中是 systemd-journald - 首先是优先级/设施信息(包含在 中<>
),然后是一个非常特定格式的时间戳,这似乎是通常提到的to 作为标签,然后是消息:
\n# logger -s hi\n<13>3 月 5 日 14:04:11 i336: hi\n\n#journalctl -qn1 -o Short-iso-precise\n2021-03-05T14:04:11.430504+1100 h0nk i336[2505]: 你好\n\n
\n# logger -s -t tag hi\n<13>3 月 5 日 14:04:37 tag : hi\n\n#journalctl -qn1 -o Short-iso-precise\n2021-03-05T14:04:37.050891 +1100 h0nk标签[3151]: hi\n\n
\n# logger -s -t tag -i hi\n<13>3 月 5 日 14:04:40标签[ 3248 ]: hi\n\n# Journalctl -qn1 -o Short-iso-precise\n2021-03- 05T14:04:40.278630+1100 h0nk标签[ 3248 ]: hi\n\n
(-s
导致logger
复制它发送到 stderr 的内容;-t tag
将标签logger
使用从我的用户名更改为我指定的任何名称;并-i
添加 PID。)
我注意到,systemd-journald
解析并丢弃提供的时间戳和 PID(如果提供)并确定此信息本身(这就是 PID 始终存在的原因,以及为什么我能够在short-iso-precise
没有提供时请求毫秒):
\n# echo \'<13> Jan 1 00:00:00 test[ 1234 ]: hi\' | ncat -uU /dev/log\n\n#journalctl -qn1\n 3 月 5 日 14:06:12 h0nk 测试 [ 5593 ]: hi\n\n#journalctl -qn1 -o Short-iso-precise\n2021-03 -05T14:06:12.538712+1100 h0nk 测试[5593]: hi\n\n
从安全角度来看,这很有意义。
\n然而,我发现如果我稍微偏离格式
\n\n\n\n
<p>Mmm _d HH:MM:SS tagwithnospaces: message
然后一切都会很快变糟。
\nlogger
\'s--rfc5424
和options似乎--rfc3164
专门用于通过 UDP 或 TCP 连接到系统日志服务器。发送数据时使用这些选项会/dev/log
产生灾难性的结果。
RFC 5424 格式(第 6 节中定义的标头)从一开始就爆炸了:
\n# logger -s --rfc5424 hi\n<13>1 2021-03-05T15:05:04.773304+11:00 h0nk i336 - - [timeQuality tzKnown="1" isSynced="1" syncAccuracy="648500"] hi\n\n# journalctl -qn1 -o short-iso-precise\n2021-03-05T15:05:04.773384+1100 h0nk logger[29306]: 1 2021-03-05T15:05:04.773304+11:00 h0nk i336 - - [timeQuality tzKnown="1" isSynced="1" syncAccuracy="648500"] hi\n
Run Code Online (Sandbox Code Playgroud)\n奇怪的是,虽然 RFC 3164 格式(在第 4.1.2 节中定义的标头)在很大程度上类似于……在没有logger
指定 RFC 选项的情况下使用的任何格式,即使添加 RFC 3164 的主机名字段也足以破坏事情:
\n# logger -s --rfc3164 hi\n<13>3 月 5 日 14:20:51 h0nk i336: hi\n\n# Journalctl -qn1 -o Short-iso-precise\n2021-03-05T14:20: 51.638518+1100 h0nk 未知[27148]: h0nk i336: hi\n ^ Oo \n\n
附带问题:我猜 RFC 格式保留了领先的<nnn>
优先级字段,以便状态信息(“紧急”、“关键”等)始终正确传输。它是否正确?
日期本身似乎也是一个特别敏感的值。即使稍微改变它也会立即导致systemd-journald
将整行视为已损坏:
\n# echo \'<13>1 月 1 日 00:00:00 测试[1234]: hi\' | ncat -uU /dev/log\n ^两个空格\n# Journalctl -qn1 -o Short-iso-precise\n2021-03-05T14:17:04.484309+1100 h0nk 测试[21585]: hi\n\n
\n# echo \'<13>1 月 1 日 00:00:00 测试[1234]: hi\' | ncat -uU /dev/log\n ^一个空格\n# Journalctl -qn1 -o Short-iso-precise\n2021-03-05T14:06:23.414986+1100 h0nk ncat[5877]: Jan 1 00:00:00测试[1234]:嗨\n\n
有趣的是,BusyBox 的 syslogd 还仔细检查日期 ( syslogd.c:829 ),以对某些字符的位置做出精确的、硬编码的假设:
\n\n/* Jan 18 00:11:22 msg... */\n/* 01234567890123456 */\nif (len >= 16 && msg[3] == \' \' && msg[6] == \' \ '\n && msg[9] == \':\' && msg[12] == \':\' && msg[15] == \' \'\n) {
(Busybox syslogd 还引用了L286中正好 15 个字符长的时间。)
\n我很感兴趣为什么日期似乎需要如此仔细地指定。
\n我发现 glibc 的实现syslog()
( syslog.c:223 ) 很有洞察力,值得研究:
它使用格式“ %h %e %T
”
%h
-> %b
; %b
= 根据区域设置的缩写月份名称%e
= 月份中的某天,带前导空格%T
= 时间就像%H:%M:%S
msg[15]\xc2\xa0==\xc2\xa0\'\xc2\xa0\'
检查(!)相匹配(完全令人麻木)它使用 (glibc-internal?) 函数strftime_l()
,该函数(如time.h:101中所述)“从提供的语言环境而不是全局语言环境中获取信息”;strftime_l()
这里传递的是_nl_C_locobj_ptr
(在locale.h:17中定义的),它是一个内部指针,指向(在xlocale.c:34_nl_C_locobj
中定义的)对 C 语言环境定义的(也是内部的)glibc 全局引用。
logger
根据调用的模式使用不同的标头格式化函数:syslog_rfc3164_header()
、syslog_rfc5424_header()
和syslog_local_header()
。其中重要的部分syslog_local_header()
是:
\nif (ctl->pid)\n snprintf(pid, sizeof(pid), "[%d]", ctl->pid);\n...\nxasprintf(&ctl->hdr, "<%d>% s %s%s: ", ctl->pri, rfc3164_current_time(),\n ctl->tag, pid);
又是那种格式。优先级、时间、标签、PID。
\nrfc3164_current_time()
是 的包装器gettimeofday()
,localtime()
它捆绑了缩写的英文月份名称列表,作为 glibc 语言环境舞蹈的便携式替代品。
鉴于 RFC 3164 的日期格式与“本地”“/dev/log
格式”中使用的日期非常相似,因此重用日期格式化函数非常有意义。但值得注意的是,这是唯一可以重用的,因为“本地”格式作为一个整体仍然与 RFC 3164 格式不同。
问题:该/dev/log
格式的来源是什么?
logger
“本地”规范化是我能够用/dev/log
与网络/RFC 格式不同的名称来消除格式歧义的最接近的规范化。我还没有发现任何其他地方试图命名这种区别,它只是使用它。
我还没有测试过其他 syslog 守护进程(如 rsyslog、syslog-ng 等),并且我不知道它们是否接受 RFC 格式的文本行/dev/log
,但鉴于 BusyBox 的准确性,我不会如果这是某种违规行为,请不要感到惊讶......
...但与此同时,什么标准或政策首先将这种行为定义为违规?
\n我的印象是这是“按照惯例”的标准,并且由于在实践中使用了精确特定的解析器,因此明确的批准已被回避。
\n这个假设正确吗?
\n注意。我偶然发现了对文件本身重要性问题的一个很好的答案/dev/log
,它指出在 chroot 中运行的应用程序可能会发送到相对/dev/log
路径。这是一个很好的观点,我/dev/log
非常使用“格式”,因为需要给它正确的名称。
也许man rsyslogd
给出了一个重要的提示:
/dev/log
The Unix domain socket to from where local syslog messages are
read.
Run Code Online (Sandbox Code Playgroud)
请注意“本地系统日志消息”。这意味着 RFC 3164 的 HOSTNAME 丢失,但其余部分似乎遵循该格式。此外,系统日志守护进程似乎在记录消息之前添加了缺少的主机名字段。
如果您的strace
应用程序创建系统日志消息,您可以看到类似这样的内容(来自strace -f logger -t demo foobar
):
...
socket(AF_UNIX, SOCK_DGRAM, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/dev/log"}, 110) = 0
...
sendto(3, "<13>Apr 28 11:34:21 demo: foobar", ...) = 32
...
Run Code Online (Sandbox Code Playgroud)
确切的作用systemd-journald
没有记录,而且很可能不是标准的(正如 Lennart Poettering 在邮件列表主题“Q:系统日志中的非 ASCII”中承认的那样)。
归档时间: |
|
查看次数: |
2010 次 |
最近记录: |