我正在写一个用syslog()发送日志的程序,然后我配置了rsyslog服务,把日志保存在Linux下的一个文件中,这个过程大部分时间都是正常的,但是有时候有些日志并没有发送到rsyslog,而是我用journalctl -f -u Myservice命令的时候可以看到,我用的是Linux的Debian Jessie版本,你知道是什么问题,怎么解决吗?
syslog()
rsyslog
Linux
journalctl -f -u Myservice
Debian Jessie
ogsagwnx1#
Process calls syslog()--写入--〉/dev/log = /run/systemd/journal/dev-log--读取者--〉systemd-journald--转发到--〉/run/systemd/journal/syslog--读取者--〉rsyslogd
Process calls syslog()
/dev/log = /run/systemd/journal/dev-log
systemd-journald
/run/systemd/journal/syslog
rsyslogd
[...] [Socket] Service=systemd-journald.service ListenDatagram=/run/systemd/journal/dev-log Symlinks=/dev/log SocketMode=0666 [...]
在上述插座单元中,有两件重要的事情:
$ ls -l /dev/log lrwxrwxrwx 1 root root 28 sept. 14 09:47 /dev/log -> /run/systemd/journal/dev-log $ ls -l /run/systemd/journal/dev-log srw-rw-rw- 1 root root 0 sept. 14 09:47 /run/systemd/journal/dev-log
因此,任何调用syslog()的进程实际上都写入到 /dev/log 中,/dev/log 是 /run/systemd/journal/dev-log 的同义词。当systemd-journald从这个套接字读取时,这使得它捕获所有写入到 /dev/log中的进程的日志。但是systemd实现了一种机制,将这些日志转发到任何“注册”的服务。有一个 syslog.socket 单元用于设置 /run/systemd/journal/syslog 套接字:
[...] [Socket] ListenDatagram=/run/systemd/journal/syslog [...]
相应的 syslog.service 随后触发。后者实际上是到实际syslog服务的符号链接(例如rsyslogd或syslog-ng)。下面是一个示例,其中它是到 rsyslog.service 的符号链接:
$ ls -l /etc/systemd/system/syslog.service lrwxrwxrwx 1 root root 35 juin 5 2021 /etc/systemd/system/syslog.service -> /lib/systemd/system/rsyslog.service
后一服务的内容执行rsyslogd守护进程:
[...] [Service] Type=notify ExecStart=/usr/sbin/rsyslogd -n -iNONE [...]
我们可以通过查看 syslog 服务(字段“TriggeredBy”)的状态来验证其激活:
$ systemctl status syslog | cat * rsyslog.service - System Logging Service Loaded: loaded (/lib/systemd/system/rsyslog.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2022-09-14 09:47:22 CEST; 32min ago TriggeredBy: * syslog.socket Docs: man:rsyslogd(8) https://www.rsyslog.com/doc/ Main PID: 728 (rsyslogd) Tasks: 4 (limit: 18404) Memory: 3.9M CGroup: /system.slice/rsyslog.service `-728 /usr/sbin/rsyslogd -n -iNONE sept. 14 09:47:22 xxx systemd[1]: Starting System Logging Service... sept. 14 09:47:22 xxx rsyslogd[728]: imuxsock: Acquired UNIX socket '/run/systemd/journal/syslog' (fd 3) from systemd. [v8.2001.0]
上面的启动消息显示rsyslogd已通过unix套接字 /run/systemd/journal/syslog(文件描述符id 3)。这由rsyslogd的imuxsock模块管理。这确实是rsyslogd进程打开的文件描述符的一部分:
$ sudo ls -l /proc/`pidof rsyslogd`/fd total 0 lr-x------ 1 root root 64 sept. 14 09:47 0 -> /dev/null l-wx------ 1 root root 64 sept. 14 09:47 1 -> /dev/null l-wx------ 1 root root 64 sept. 14 09:47 10 -> /var/log/kern.log l-wx------ 1 root root 64 sept. 14 09:47 11 -> /var/log/mail.log l-wx------ 1 root root 64 sept. 14 09:47 2 -> /dev/null lrwx------ 1 root root 64 sept. 14 09:47 3 -> 'socket:[1339]' lr-x------ 1 root root 64 sept. 14 09:47 4 -> /dev/urandom lrwx------ 1 root root 64 sept. 14 09:47 5 -> 'socket:[36221]' lr-x------ 1 root root 64 sept. 14 09:47 6 -> /proc/kmsg lrwx------ 1 root root 64 sept. 14 09:47 7 -> 'socket:[36999]' l-wx------ 1 root root 64 sept. 14 09:47 8 -> /var/log/syslog l-wx------ 1 root root 64 sept. 14 09:47 9 -> /var/log/auth.log
systemd-journald的configuration决定是否将从 /run/systemd/journal/dev-log 读取的内容转发到 /run/systemd/journal/syslog:
$ cat /etc/systemd/journald.conf | grep ForwardToSyslog #ForwardToSyslog=yes
上面的注解行表示默认值为**“yes”**。
如果进程发送的一些日志在rsyslogd的输出中没有看到,但在systemd-journald的输出中看到,这可能意味着rsyslogd与应用程序相比启动得不够早。后者的日志记录由systemd-journald读取,但不转发到rsyslogd。后者从systemd的 multi-user.target 开始,而systemd-journald在系统启动的最开始启动。为了验证这一点,systemctl status syslog.service的结果显示激活日期,并将其与 systemd-journald.service 和应用程序的激活日期进行比较。应用程序的服务文件中可能缺少类似“After=syslog.service”的同步密钥。
systemd
systemctl status syslog.service
https://www.freedesktop.org/wiki/Software/systemd/syslog/
sz81bmfz2#
这完全取决于rsyslog服务是否运行,遇到问题时请检查rsyslog是否运行。
luaexgnf3#
最后,我找到了一个很好的答案。在rsyslog配置文件中,我们可以添加不同的方法来获取消息。我有许多使用contains过滤器的过滤器。这显著降低了性能,因为它需要完全搜索过滤器值的字符串。然后我发现startswith过滤器在搜索字符串中的值方面要好得多。我更改了消息结构,以便可以使用startswith过滤器。然后我将rsyslog过滤器更改为startswith。现在性能好多了,并且没有消息发送到日志。语法如下所示::msg, startswith, "val" # instead of (:msg, contains, "val")
contains
startswith
:msg, startswith, "val" # instead of (:msg, contains, "val")
3条答案
按热度按时间ogsagwnx1#
不严格地说,使用systemd时,日志的管理方式如下:
Process calls syslog()
--写入--〉/dev/log = /run/systemd/journal/dev-log
--读取者--〉systemd-journald
--转发到--〉/run/systemd/journal/syslog
--读取者--〉rsyslogd
让我们更详细地了解一下...
在上述插座单元中,有两件重要的事情:
因此,任何调用
syslog()
的进程实际上都写入到 /dev/log 中,/dev/log 是 /run/systemd/journal/dev-log 的同义词。当systemd-journald从这个套接字读取时,这使得它捕获所有写入到 /dev/log中的进程的日志。但是systemd实现了一种机制,将这些日志转发到任何“注册”的服务。有一个 syslog.socket 单元用于设置 /run/systemd/journal/syslog 套接字:
相应的 syslog.service 随后触发。后者实际上是到实际syslog服务的符号链接(例如rsyslogd或syslog-ng)。下面是一个示例,其中它是到 rsyslog.service 的符号链接:
后一服务的内容执行
rsyslogd
守护进程:我们可以通过查看 syslog 服务(字段“TriggeredBy”)的状态来验证其激活:
上面的启动消息显示
rsyslogd
已通过unix套接字 /run/systemd/journal/syslog(文件描述符id 3)。这由rsyslogd
的imuxsock模块管理。这确实是rsyslogd
进程打开的文件描述符的一部分:systemd-journald
的configuration决定是否将从 /run/systemd/journal/dev-log 读取的内容转发到 /run/systemd/journal/syslog:上面的注解行表示默认值为**“yes”**。
回答操作员的问题
如果进程发送的一些日志在
rsyslogd
的输出中没有看到,但在systemd-journald
的输出中看到,这可能意味着rsyslogd
与应用程序相比启动得不够早。后者的日志记录由systemd-journald
读取,但不转发到rsyslogd
。后者从systemd
的 multi-user.target 开始,而systemd-journald在系统启动的最开始启动。为了验证这一点,
systemctl status syslog.service
的结果显示激活日期,并将其与 systemd-journald.service 和应用程序的激活日期进行比较。应用程序的服务文件中可能缺少类似“After=syslog.service”的同步密钥。
更多参考
https://www.freedesktop.org/wiki/Software/systemd/syslog/
sz81bmfz2#
这完全取决于
rsyslog
服务是否运行,遇到问题时请检查rsyslog
是否运行。luaexgnf3#
最后,我找到了一个很好的答案。在
rsyslog
配置文件中,我们可以添加不同的方法来获取消息。我有许多使用contains
过滤器的过滤器。这显著降低了性能,因为它需要完全搜索过滤器值的字符串。然后我发现startswith
过滤器在搜索字符串中的值方面要好得多。我更改了消息结构,以便可以使用startswith
过滤器。然后我将rsyslog
过滤器更改为startswith
。现在性能好多了,并且没有消息发送到日志。语法如下所示::msg, startswith, "val" # instead of (:msg, contains, "val")