在 linux 中,一个典型的日志记录过程如下:
内核使用 printk() 函数往内核空间的一个 ring buffer 中写入日志消息. 该消息有三种方法可以被用户空间的应用所获取:
我们可以通过执行 dmesg 命令来输出 ring buffer 中的内容. 或者通过 klogd(Kernel Log Daemon) 从 /proc/kmsg(若没有挂载/proc则会调用sys_syslog系统API) 来读取 ring buffer 中的日志消息,并将之发送到 syslogd 或者 输出到终端上。
用户空间一般通过 syslogd(8) 来记录日志. syslogd一般通过监听 /dev/log UNIX域套接字来获取日志消息,但也可以通过配置同时监听多个其他UNIX域套接字, 同时他也可以监听网络 Socket,默认 syslog 监听 UDP 协议的 514 号端口,但协议和端口都可以进行配置,它还能够从 klogd(8) 中获取日志消息,但不能直接从 /proc/kmsg 中获取日志消息.
syslogd 一般会将获取到的日志消息写入到指定的日志文件中去, 除此之外还可以将日志写入命名管道,转发给给其他主机,作为命令参数甚至是写入数据库中.
用户空间的应用一般通过libc提供的 syslog(3) 函数来记录日志. 该函数会将日志信息发送给 /dev/log,不过若应用程序通过 chroot(2) 切换了root路径,则日志实际上可能被发送到 /chrooted/named/dev/log. 这种情况下需要配置 syslogd 监听新位置的UNIX域套接字.
另外,syslog 协议仅仅是一个数据包协议,应用程序不一定要通过 syslog 函数来写日志,它可以使用任何方式只要能与 syslogd 监听的套接字通讯就可以了。
最后,上面讲的都是经典的 syslogd 的行为,新的日志守护进程(比如 rsyslog 或者 syslog-ng)在细节上可能会有所不同,比如最新版的 rsyslogd 在 systemd 系统上已经不再监听 /dev/log 而是改为监听 /run/systemd/journal/syslog。
systemd 通过 systemd-journald 来进行日志管理,它的日志处理方式与经典的 linux 日志处理方式不太一样:
rsyslogd 在 systemd 系统中可以通过两种方式来获取日志消息。

