systemd/journald - archLinux下的系统服务管理

systemd

Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置。
systemd 是一个 Linux 系统基础组件的集合,提供了一个系统和服务管理器,运行为 PID 1 并负责启动其它程序。功能包括:支持并行化任务;同时采用 socket 式与 D-Bus 总线式启用服务;按需启动守护进程(daemon);利用 Linux 的 cgroups 监视进程;支持快照和系统恢复;维护挂载点和自动挂载点;各服务间基于依赖关系进行精密控制。systemd 支持 SysV 和 LSB 初始脚本,可以替代 sysvinit。除此之外,功能还包括日志进程、控制基础系统配置,维护登陆用户列表以及系统账户、运行时目录和设置,可以运行容器和虚拟机,可以简单的管理网络配置、网络时间同步、日志转发和名称解析等。
在历史上,systemd中的“服务”(service)被称作守护进程(daemon),它们在后台运行(即没有UI、不与终端交互),等待特定事件的发生并提供服务。
Systemd 可以管理所有系统资源。不同的资源统称为 Unit(单位)。
unit通常包括但不限于:服务(.service)、挂载点(.mount)、设备(.device)和套接字(.socket)。

systemd-journald - systemd的日志管理

breif introduction

systemd 提供了自己的日志系统(logging system),称为 journal。使用 systemd 日志,无需额外安装日志服务(syslog)。使用 journalctl(1)命令读取日志。它作为由systemd管理的服务运行。

使用systemd 的 Journal,如果您只需要本地日志,则不需要 syslog-ng (syslog-ng 是 syslog 的一种实现)

systemd-journald将日志条目写入/run/log/journal/ machine-id /或/var/log/journal/ machine-id /中带有“.journal”后缀的文件中。如果守护程序不干净地停止,或者发现文件已损坏,则使用“.journal~”后缀重命名它们,并且systemd-journald开始写入新文件。当/var/log/journal不可用或在/etc/systemd/journald.conf(5)配置文件中设置Storage=volatile时,将使用/run/目录
systemd-journald程序以二进制格式而不是纯文本日志文件存储日志条目, 下面是一些常用命令的示例:

  • journalctl -r:以逆序的方式显示日志的所有内容。

  • journalctl -u UNIT:显示与指定的UNIT文件相关联的日志条目。

  • journalctl -b[=ID]-r:以逆序的方式显示自上次成功启动以来(或者指定的引导ID)的日志条目。

  • journalctl -f:提供类似于tail -f(跟踪)的功能。

systemd-journald的工作原理

  • 它从/dev/kmsg读取内核日志数据。
  • 它从GNU C库的syslog()函数读取应用程序日志数据,该函数通过符号链接 /dev/log(指向/run/systemd/journal/dev-log)。
  • 它通过在/run/systemd/journal/stdout上监听AF_LOCAL(AF_UNIX)流套接字,接收来自systemd管理服务的日志数据。
  • 它通过在/run/systemd/journal/socket上监听AF_LOCAL数据报套接字,接收使用systemd特定日志协议(如sd_journal_sendv()等)的程序发送的日志数据。
    它将所有这些混合在一起。
  • 它将日志写入一组系统范围和每个用户的日志文件,位于/run/log/journal/或/var/log/journal/中。
  • 如果配置了转发到syslog,则它可以连接(作为客户端)到/run/systemd/journal/syslog上的AF_LOCAL数据报套接字,并将日志数据写入那里。
  • 如果配置了,它还可以使用可写的/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输入方法来实现这一点。

以上内容来自于这里
systemd-journald官方文档
有关systemd-journald更多的信息,详细介绍了/run/systemd/journal目录下不同socket的作用

linux系统日志

rsyslog / systemd-journald 守护进程既能接受用户进程输出的日志, 又能接受内核日志
用户进程是通过syslog函数创建系统日志的,该函数将系统日志输出到一个UNIX本地域socket类型文件/dev/log中
内核日志由printk等函数打印至内核的环状缓存(ring buffer)中, 环状缓存的内容直接映射至/proc/kmsg 和 /dev/kmsg 中,proc/kmsg 和 dev/kmsg的区别,rsyslog从/proc/kmsg读取,而journald可以从/dev/kmsg和/proc/ksmg读取。
下图总结了linux的日志系统:

误区

/etc/init.d 是旧 SyS init 进程的一部分,并保留在基于 systemd 初始化的系统中以实现向后兼容性。详情
sysctl 是一个实用程序,用于实时(/proc/sys)和通过 sysctl.conf 启动时设置内核参数。
systemd 是较新的初始化过程。
systemctl 是一个实用程序,用于启动/停止和启用基于 systemd 的系统的服务。
journalctl,它是systemd用于读取systemd日志的实用程序。

systemd-coredump

核心转储(core dump)文件是程序收到信号或出现段错误崩溃,进程退出后所生成的文件

systemd-coredump(可执行文件, 在arch linux环境下位于/usr/lib/systemd/systemd-coredump)会将核心转储记录到日志中,如果可能的话还包括回溯(backtrace),并将核心转储(进程内存内容的映像)本身存储在 /var/lib/systemd/coredump 中的外部文件中
实际工作时,systemd-coredump被内核(/proc/sys/kernel/core_pattern)调用两次:一次作为处理程序,另一次在systemd-coredump@.service中将数据写入日志并处理保存核心文件。
当内核调用systemd-coredump来处理核心转储时,它在特权模式下运行,并将连接到systemd-coredump.socket单元创建的套接字,该套接字将生成一个非特权的systemd-coredump@.service实例来处理核心转储。因此,systemd-coredump.socket和systemd-coredump@.service是辅助单元,用于实际处理核心转储,并受到正常服务管理的限制。
还可以使用–backtrace选项调用systemd-coredump。在这种情况下,systemd-coredump期望在标准输入中以日志Journal Export Format [2]的形式包含一个日志条目。该条目应包含一个MESSAGE=字段和调用者认为合理的任何其他元数据字段。systemd-coredump将以与从内核接收的核心转储相同的方式附加其他元数据字段。在这种模式下,不会将核心转储存储在日志中。

使用systemd-coredump作为core dump的处理程序时, /proc/sys/kernel/core_pattern中的内容类似于
kernel.core_pattern=|/usr/lib/systemd/systemd-coredump %P %u %g %s %t 9223372036854775808 %e
|使用管道表示core dump文件将通过管道传给后续命令,这里后续命令是systemd-coredump。百分号后各类参数表示对core dump文件进行重命名,如加入pid等等,具体内容在core手册

wsl2下systemd-coredump失效,/var/lib/systemd/coredump 中不会记录core dump文件,查看系统日志可以发现出现以下条目:Failed to connect to coredump service: No such file or directory,但是coredumpctl可以正常运行,/usr/lib/systemd/systemd-coredump文件也正常存在,该bug存在已久,一直没有得到修复

解决办法

由于内核参数kernel.core_pattern是可以通过sysctl修改的,并且该参数的默认配置本身也来于/usr/lib/sysctl.d/50-coredump.conf, 所以我们可以临时修改或者永久修改该参数来改变core dump文件存储位置为/tmp/core(这里随喜好选择即可)

首先使用 ulimit -c 1024 来修改core dump文件的大小不为0,我这里修改为1024blocks,1blocks = 512MB, 当然修改后只对目标用户当前进程及其子进程(session)有效,永久修改可以将其加入login shell的start up文件中(如/etc/profile),或者在/etc/security/limits.conf 中加入 一行 * hard core 1024 表示修改系统的硬限制为1024blocks

  • 临时修改, 重启后失效: sudo sysctl -w kernel.core_pattern=/tmp/core
  • 永久修改: 在/etc/sysctl.d/core.conf中添加以下内容:
    kernel.core_pattern=/tmp/core之后运行
    sysctl -p /etc/sysctl.d/50-coredump.conf
    方法来源

systemd/journald - archLinux下的系统服务管理
http://example.com/2023/11/26/systemd/
作者
李凯华
发布于
2023年11月26日
许可协议