了解Linux中的日志记录


62

据我了解,Linux内核记录到/proc/kmsg文件(主要是与硬件相关的消息)和/dev/log套接字中?还有其他地方吗 其他应用程序也能够向/proc/kmsg或发送消息/dev/log吗?最后但并非最不重要的,我是正确的,这是系统日志守护程序(rsyslog现在syslog-ng的),它来自这两个地方检查邮件,然后分发给那些喜欢各种文件/var/log/messages或者/var/log/kern.log甚至是中央系统日志服务器?

Answers:


81

简化后,它或多或少是这样的:

内核(使用printk()函数)将消息记录到内核​​空间中的环形缓冲区。这些消息可以通过两种方式提供给用户空间应用程序:通过/proc/kmsg文件(/proc已安装)(通过已安装的文件)和通过sys_syslogsyscall。

有两个主要的应用程序读取(并在某种程度上可以控制)内核的环形缓冲区:dmesg(1)klogd(8)。前者旨在按用户要求运行,以打印环形缓冲区的内容。后者是一个守护程序,它从/proc/kmsg(或调用sys_syslog,如果/proc未挂载)读取消息并将其发送到syslogd(8)或控制台。那涵盖了内核方面。

在用户空间中,存在syslogd(8)。这是一个守护程序,它侦听许多UNIX域套接字(主要是/dev/log,但也可以配置其他套接字),并且可以侦听UDP端口514以获取消息。它还接收来自klogd(8)syslogd(8)无关/proc/kmsg)的消息。然后,将这些消息写入/log或命名管道中的某些文件中,或将它们发送到某些远程主机(通过syslogUDP端口514上的协议),如中所配置/etc/syslog.conf

用户空间应用程序通常使用该libc功能syslog(3)来记录消息。 libc将这些消息发送到UNIX域套接字/dev/log(由读取syslogd(8)),但是如果对应用程序进行了chroot(2)-ed处理,则消息最终可能会写入其他套接字,即to /var/named/dev/log。对于发送这些日志并syslogd(8)同意这些套接字位置的应用程序来说,这当然是必不可少的。由于这些原因,syslogd(8)可以将其配置为侦听标准之外的其他套接字/dev/log

最后,该syslog协议只是数据报协议。没有什么能阻止应用程序将syslog数据报发送到任何UNIX域套接字(只要其凭据允许它打开套接字),syslog(3)libc完全绕开了该功能。如果数据报格式正确,则syslogd(8)可以像通过消息发送消息一样使用它们syslog(3)

当然,以上内容仅涵盖“经典”测井理论。其他守护程序(例如rsyslogsyslog-ng,如您所提到的)可以代替plain syslogd(8),并做各种漂亮的事情,例如通过加密的TCP连接将消息发送到远程主机,提供高分辨率的时间戳等等。还有systemd,它正在吞噬Linux的UNIX部分。 systemd有其自己的日志记录机制,但该故事必须由其他人讲述。:)

与* BSD世界的差异:

在* BSD上没有klogd(8)/proc或者不存在(在OpenBSD上),或者几乎已经过时(在FreeBSD和NetBSD上)。 syslogd(8)从字符设备读取内核消息/dev/klog,并dmesg(1)用于/dev/kmem解码内核名称。只有OpenBSD有一个/dev/log。FreeBSD使用两个UNIX域套接字/var/run/logvar/rub/logpriv而NetBSD有一个/var/run/log


3
nit:rsyslog现在比较流行(Fedora,Debian的默认设置),并且不使用单独的klogd。看起来syslog-ng也没有(按偏好)。
sourcejedi

@sourcejedi我已经有好几年没有跟上Linux了,但是IIRC 之所以rsyslog没有使用,klogd(8)是因为它的根源可以追溯到最近,而不是因为它最近做出了明确的决定来取消它。我的记忆可能会失败。无论如何,就像我说的那样,我只是试图涵盖“经典”日志记录。
lcd047

1
@ lcd047,@ sourcejedi,感谢您的答复!我有一个rsyslogd正在运行的Debian 7系统和一个正在运行的Ubuntu 12.04,syslog-ng它们都/proc/kmsg根据开启了文件lsof,即klogd未使用。我注意到的另一件有趣的事情是,/proc/kmsg如果没有syslog守护程序正在运行,并且可以使用例如cat或文本编辑器查看日志消息,则日志消息将存储在文件中。但是,由于这些消息在查看后会消失,因此只能查看一次。最后但并非最不重要的一点是,执行dmesg不会清除/proc/kmsg文件的内容。
马丁

1
@Martin /proc/kmsg不是常规文件,没有“存储”在那里,而只是内核环形缓冲区的视图。您可以cat准确地阅读它,因为您没有klogd(8)跑步(应该跑步klogd(8)cat /proc/kmsg会阻塞)。 dmesg(1)从而/dev/kmsg不是从读取消息/proc/kmsg; 如果您告诉它,它也可以清除缓冲区。
lcd047

1
systemd has its own logging mechanisms, but that story would have to be told by somebody else. :)-请您告诉,您很有才华:-)
Flavius

51

正如其作者所说,另一个答案解释了Linux中的“经典日志记录”。如今,这并不是很多系统中工作的方式。

内核

内核机制已经改变。

内核将输出生成到内存中的缓冲区。应用程序软件可以通过两种方式访问​​它。日志子系统通常以名为的伪FIFO访问它/proc/kmsg。该日志信息源一次只能读取一次,因此无法在日志读取器之间共享。如果有多个进程共享,则每个进程仅获得内核日志数据流的一部分。它也是只读的。

访问它的另一种方法是更新的/dev/kmsg字符设备。这是一个可在多个客户端进程之间共享的读写接口。如果多个进程共享它,它们都将读取同一完整的数据流,而不会互相影响。如果他们打开它进行写访问,他们也可以将消息注入内核的日志流,就像它们是由内核生成的一样。

/proc/kmsg/dev/kmsg以非RFC-5424格式提供日志数据。

应用领域

应用程序已更改。

GNU C库的syslog()功能主要尝试连接到AF_LOCAL名为的数据报套接字,/dev/log并向其中写入日志条目。(syslog()如今,BSD C库的功能/var/run/log用作套接字名称,并/var/run/logpriv首先尝试。)当然,应用程序可以具有自己的代码来直接执行此操作。毕竟,库函数只是在应用程序自己的进程上下文中执行的代码(用于打开,连接,写入和关闭套接字)。

如果正在侦听计算机上的AF_INET/ AF_INET6数据报套接字,则应用程序还可以通过UDP将RFC 5424消息发送到本地RFC 5426服务器。

由于过去二十年来daemontools世界的压力,许多dæmons支持以不使用GNU syslog()C库函数或UDP套接字的方式运行,而只是将其日志数据吐出到标准错误中。普通的Unix时尚。

通常使用nosh和daemontools系列进行日志管理

借助daemontools系列工具集,日志记录具有很大的灵活性。但是一般来说,整个家庭的想法是每个“主”守护程序都有一个关联的“日志记录”守护程序。“主”守护程序的工作方式与非守护进程一样,并将其日志消息写入标准错误(或标准输出),服务管理子系统将其安排为通过管道进行连接(管道保持打开状态,以便不会丢失日志数据)服务重启)到“日志记录”守护程序的标准输入。

所有的“记录”守护程序都运行一个在某处记录的程序。通常,该程序类似于multilogcyclog从标准输入中读取内容,并将日志文件写入(以纳秒为单位加时间戳)严格限制大小,自动旋转,互斥写入的目录。通常,这些守护程序也都在单个专用非特权用户帐户的支持下运行。

因此,最终会出现一个很大程度上是分布式的日志记录系统,其中每个服务的日志数据都是单独处理的。

一个可以运行类似klogdsyslogdrsyslogd下一个daemontools的家庭服务管理。但是daemontools界在很多年前就意识到,带有“日志记录”守护进程的服务管理结构非常适合以更简单的方式进行操作。无需将所有日志流都散布到一个大型的Mash mash中,解析日志数据,然后将这些流散回到单独的日志文件中;然后(在某些情况下)在侧面用螺栓固定一个不可靠的外部圆木旋转机构。作为其标准日志管理的一部分,daemontools-family结构已经进行了日志轮换,日志文件写入和流分离。

此外:使用所有服务中通用的工具丢弃特权的链式加载模型意味着日志记录程序不需要超级用户特权;UCSPI模型意味着他们只需要关心流与数据报传输之间的差异。

nosh工具集就是例证。虽然可以立即rsyslogd在其下运行,并且仅以/run/log旧方式管理内核,和UDP日志输入;它提供了记录这些东西更多的“本土daemontools的”方式:

  • klogd,从读取的服务/proc/kmsg,只是该日志流写入到其标准错误。这是通过一个名为的简单程序完成的klog-read。关联的日志记录守护程序将其标准输入上的日志流馈送到/var/log/sv/klogd日志目录中。
  • 一种local-syslog-read服务,该服务从BSD上的/dev/log/run/log)读取数据报,并将该日志流简单地写入其标准错误。这是通过名为的程序完成的syslog-read。关联的日志记录守护程序将其标准输入上的日志流馈送到/var/log/sv/local-syslog-read日志目录中。
  • 一个udp-syslog-read在UDP syslog端口上侦听,读取发送给它的内容并将该日志流写入其标准错误的服务。同样,该程序为syslog-read。关联的日志记录守护程序将其标准输入上的日志流馈送到/var/log/sv/udp-syslog-read日志目录中。
  • (在BSD上)一种local-priv-syslog-read服务,该服务从/run/logpriv该日志流读取数据报并将其简单写入其标准错误。同样,该程序为syslog-read。关联的日志记录守护程序将其标准输入上的日志流馈送到/var/log/sv/local-priv-syslog-read日志目录中。

该工具集还附带了一个export-to-rsyslog工具,该工具可以监视一个或多个日志目录(使用非侵入式日志游标系统),并以RFC 5424形式通过网络将新条目发送到指定的RFC 5426服务器。

使用systemd进行日志管理

systemd具有单个整体日志管理程序systemd-journald。这作为由systemd管理的服务运行。

  • 它读取/dev/kmsg内核日志数据。
  • 它从GNU C库的功能读取/dev/log(到的符号链接/run/systemd/journal/dev-log)应用程序日志数据syslog()
  • 它在AF_LOCALat 的流套接字上侦听/run/systemd/journal/stdout来自systemd管理的服务的日志数据。
  • 它在AF_LOCAL数据报套接字上侦听/run/systemd/journal/socket来自说特定于systemd的日记协议(即sd_journal_sendv()等)程序的日志数据。
  • 它将所有这些混合在一起。
  • 它在/run/log/journal/或中写入一组系统范围和每个用户的日记文件/var/log/journal/
  • 如果已配置(转发到syslog),则它可以连接(作为客户端)到AF_LOCAL数据报套接字,/run/systemd/journal/syslog并在其中写入日志数据。
  • 如果已配置,它将使用可写/dev/kmsg机制将日志数据写入内核缓冲区。
  • 如果已配置,它将日志数据写入终端和控制台设备。

如果该程序崩溃或服务停止,则整个系统都会发生错误的事情。

systemd本身安排将标准输出和(某些)服务的错误附加到/run/systemd/journal/stdout套接字。因此,以常规方式记录到标准错误的守护程序会将其输出发送到日志。

这完全替代了klogd,syslogd,syslog-ng和rsyslogd。

现在,这些要求是特定于systemd的。在systemd系统上,它们不必成为的服务器端/dev/log。相反,他们采用以下两种方法之一:

  • 它们成为的服务器端/run/systemd/journal/syslog,(如果您还记得的话)systemd-journald尝试连接并向其中写入日志数据。几年前,可以配置rsyslogd的imuxsock输入方法来做到这一点。
  • 他们使用特定于systemd的库直接从systemd日记中读取,该库了解二进制日记格式,并且可以监视日记文件和目录以查找要添加的新条目。如今,可以配置rsyslogd的imjournal输入方法来做到这一点。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.