systemd 初始化系统。它拥有进程 ID 1。systemd 由内核直接启动,并且抵抗信号 9,该信号通常会终止进程。所有其他程序都由 systemd 或其子进程之一直接启动。systemd 是 System V init 守护进程的替代品,并且与 System V init 完全兼容(通过支持 init 脚本)。
systemd 的主要优势在于,它通过并行启动服务来大大加快启动时间。此外,systemd 仅在真正需要时才启动服务。守护进程不会在启动时无条件地启动,而是在首次需要时启动。systemd 还支持内核控制组 (cgroups)、创建快照以及恢复系统状态。有关更多详细信息,请参阅 https://www.freedesktop.org/wiki/Software/systemd/。
Windows Subsystem for Linux (WSL) 允许在 Microsoft Windows 操作系统下运行 Linux 应用程序和发行版。WSL 使用其 init 进程而不是 systemd。要在运行 WSL 中的 openSUSE Leap 中启用 systemd,请安装自动执行该过程的 wsl_systemd 模式
>sudozypper in -t pattern wsl_systemd
或者,您可以编辑 /etc/wsl.conf 并手动添加以下行
[boot] systemd=true
请记住,WSL 中对 systemd 的支持是部分性的——systemd 单元文件必须具有合理的进程管理行为。
以下部分解释了 systemd 背后的概念。
systemd 是 Linux 的系统和会话管理器,与 System V 和 LSB init 脚本兼容。systemd 的主要功能包括
并行化能力
用于启动服务的套接字和 D-Bus 激活
按需启动守护进程
使用 Linux cgroups 跟踪进程
创建快照和恢复系统状态
维护挂载点和自动挂载点
实现精细的基于事务的依赖性服务控制逻辑
单元配置文件包含有关服务、套接字、设备、挂载点、自动挂载点、交换文件或分区、启动目标、监视的文件系统路径、由 systemd 控制和监督的计时器、临时系统状态快照、资源管理切片或外部创建的进程组的信息。
“单元文件” 是 systemd 用于以下内容的通用术语
服务。 关于进程的信息(例如,运行守护进程);文件以 .service 结尾
目标。 用于分组单元以及在启动期间作为同步点;文件以 .target 结尾
套接字。 关于 IPC 或网络套接字或文件系统 FIFO 的信息,用于基于套接字的激活(如 inetd);文件以 .socket 结尾
路径。 用于触发其他单元(例如,在文件更改时运行服务);文件以 .path 结尾
计时器。 关于由计时器控制的计时器,用于基于计时器的激活;文件以 .timer 结尾
挂载点。 通常由 fstab 生成器自动生成;文件以 .mount 结尾
自动挂载点。 关于文件系统自动挂载点的信息;文件以 .automount 结尾
交换。 关于交换设备或用于内存分页的文件;文件以 .swap 结尾
设备。 关于在 sysfs/udev(7) 设备树中公开的设备单元的信息;文件以 .device 结尾
范围/切片。 用于分层管理一组进程的资源的概念;文件以 .scope/.slice 结尾
有关 systemd 单元文件的更多信息,请参阅 https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html
System V init 系统使用几个命令来处理服务——init 脚本、insserv、telinit 等。systemd 使服务管理更加容易,因为只有一个命令可以处理大多数服务相关任务:systemctl。它使用“命令加子命令”表示法,如 git 或 zypper
systemctl GENERAL OPTIONS SUBCOMMAND SUBCOMMAND OPTIONS
请参阅 man 1 systemctl 以获取完整的手册。
如果输出发送到终端(而不是管道或文件,例如),systemd 命令默认会将长输出发送到分页器。使用 --no-pager 选项关闭分页模式。
systemd 还支持 bash 完成,允许您输入子命令的第一个字母,然后按 →|。此功能仅在 bash shell 中可用,并且需要安装 bash-completion 包。
管理服务的子命令与使用 System V init 管理服务的命令相同(start、stop、...)。服务管理命令的一般语法如下
systemdsystemctl reload|restart|start|status|stop|... MY_SERVICE(S)
rcMY_SERVICE(S) reload|restart|start|status|stop|...
systemd 允许您一次管理多个服务。与 System V init 一样,逐个执行 init 脚本,而是执行如下命令
>sudosystemctl start MY_1ST_SERVICE MY_2ND_SERVICE
要列出系统上所有可用的服务
>sudosystemctl list-unit-files --type=service
下表列出了 systemd 和 System V init 的最重要服务管理命令
|
任务 |
systemd 命令 |
System V init 命令 |
|---|---|---|
|
启动。 |
start |
start |
|
停止。 |
stop |
stop |
|
重新启动。 关闭服务并在之后启动它们。如果服务尚未运行,则启动它。 |
restart |
restart |
|
有条件地重新启动。 仅在服务当前正在运行时才重新启动服务。对于未运行的服务,不执行任何操作。 |
try-restart |
try-restart |
|
重新加载。 告诉服务在不中断操作的情况下重新加载其配置文件。用例:告诉 Apache 重新加载修改后的 httpd.conf 配置文件。并非所有服务都支持重新加载。 |
reload |
reload |
|
重新加载或重新启动。 如果支持重新加载,则重新加载服务,否则重新启动它们。如果服务尚未运行,则启动它。 |
reload-or-restart |
n/a |
|
有条件地重新加载或重新启动。 如果支持重新加载,则重新加载服务,否则仅在当前运行时才重新启动它们。对于未运行的服务,不执行任何操作。 |
reload-or-try-restart |
n/a |
|
获取详细状态信息。 列出有关服务状态的信息。systemd 命令显示详细信息,例如描述、可执行文件、状态、cgroup 以及服务发出的最新消息(请参阅第 10.6.9 节,“调试服务”)。System V init 中显示的详细信息级别因服务而异。 |
status |
status |
|
获取简短状态信息。 显示服务是否处于活动状态。 |
is-active |
status |
上一节中提到的服务管理命令允许您操作当前会话的服务。systemd 还允许您永久启用或禁用服务,以便在请求时自动启动或始终不可用。您可以通过 YaST 或命令行来执行此操作。
下表列出了 systemd 和 System V init 的启用和禁用命令
在命令行上启用服务时,不会自动启动它。它计划在下一次系统启动或 runlevel/target 更改时启动。要在启用服务后立即启动它,请显式运行 systemctl start MY_SERVICE 或 rc MY_SERVICE start。
|
任务 |
systemd 命令 |
System V init 命令 |
|---|---|---|
|
启用。 |
|
insserv MY_SERVICE(S),chkconfig -a MY_SERVICE(S) |
|
禁用。 |
|
insserv -r MY_SERVICE(S),chkconfig -d MY_SERVICE(S) |
|
检查。 显示服务是否已启用。 |
|
|
|
重新启用。 类似于重新启动服务,此命令首先禁用然后启用服务。对于使用默认值重新启用服务很有用。 |
|
不可用 |
|
屏蔽。 在“禁用”服务后,仍然可以手动启动它。要禁用服务,需要屏蔽它。请谨慎使用。 |
|
不可用 |
|
取消屏蔽。 屏蔽的服务只有在取消屏蔽后才能再次使用。 |
|
不可用 |
systemd 维护整个系统启动和关机过程。从这个角度来看,内核可以被认为是维护所有其他进程并根据其他程序的请求调整 CPU 时间和硬件访问的后台进程。
使用 System V init,系统启动到所谓的“运行级别”。运行级别定义了系统如何启动以及在运行系统中提供哪些服务。运行级别编号;最常用的编号是 0(关闭系统)、3(具有网络的单用户)和 5(具有网络和显示管理器的多用户)。
systemd 引入了一个新概念,即使用所谓的“目标单元”。但是,它仍然与运行级别概念完全兼容。目标单元是命名的,而不是编号的,并且具有特定的目的。例如,目标 local-fs.target 和 swap.target 挂载本地文件系统和交换空间。
目标 graphical.target 提供具有网络和显示管理器的多用户系统,相当于运行级别 5。复杂的目标,例如 graphical.target 作为“元”目标通过组合其他目标的子集来工作。由于 systemd 允许通过组合现有目标轻松创建自定义目标,因此它提供了很大的灵活性。
以下列表显示了最重要的 systemd 目标单元。有关完整列表,请参阅 man 7 systemd.special。
default.target默认启动的目标。不是一个““真实””目标,而是一个指向另一个目标的符号链接,例如 graphic.target。可以通过 YaST 永久更改(参见 第 10.4 节,“使用 YaST 管理服务”)。要在会话期间更改它,请在启动提示符处使用内核参数 systemd.unit=MY_TARGET.target。
emergency.target在控制台上启动一个最小的紧急 root shell。仅在启动提示符处将其用作 systemd.unit=emergency.target。
graphical.target启动一个具有网络、多用户支持和显示管理器的系统。
halt.target关闭系统。
mail-transfer-agent.target启动发送和接收邮件所需的所有服务。
multi-user.target启动一个具有网络的、多用户系统。
reboot.target重新启动系统。
rescue.target启动一个单用户 root 会话,没有网络。可使用基本的系统管理工具。 rescue 目标适用于解决多个系统问题,例如登录失败或修复显示驱动程序问题。
为了与 System V init 运行级别系统兼容,systemd 提供了名为 runlevelX.target 的特殊目标,它映射了编号为 X 的相应运行级别。
要检查当前目标,请使用命令:systemctl get-default
systemd 目标单元 #|
System V 运行级别 |
|
用途 |
|---|---|---|
|
0 |
|
系统关机 |
|
1, S |
|
单用户模式 |
|
2 |
|
本地多用户,无远程网络 |
|
3 |
|
具有网络的完整多用户 |
|
4 |
|
未使用/用户定义 |
|
5 |
|
具有网络和显示管理器的完整多用户 |
|
6 |
|
系统重新启动 |
systemd 忽略 /etc/inittab在 System V init 系统中,运行级别在 /etc/inittab 中配置。 systemd 不使用此配置。有关如何创建自己的可启动目标的说明,请参阅 第 10.5.5 节,“创建自定义目标”。
使用以下命令操作目标单元
|
任务 |
systemd 命令 |
System V init 命令 |
|---|---|---|
|
更改当前目标/运行级别 |
|
|
|
更改为默认目标/运行级别 |
|
不可用 |
|
获取当前目标/运行级别 |
使用 |
或者
|
|
持久地更改默认运行级别 |
使用服务管理器或运行以下命令
|
使用服务管理器或更改行
在 |
|
更改当前启动过程的默认运行级别 |
在启动提示符处输入以下选项
|
在启动提示符处输入所需的运行级别编号。 |
|
显示目标的依赖项 |
“Requires” 列出硬依赖项(必须解决的依赖项),而 “Wants” 列出软依赖项(如果可能则解决的依赖项)。 |
不可用 |
systemd 提供了分析系统启动过程的手段。您可以查看所有服务及其状态的列表(而不必解析 /var/log/)。 systemd 还允许您扫描启动过程,以了解每个服务启动消耗的时间。
要查看自启动系统以来启动的所有服务的完整列表,请输入命令 systemctl。它列出所有活动服务,如下所示(已缩短)。要获取有关特定服务的更多信息,请使用 systemctl status MY_SERVICE。
# systemctl
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
[...]
iscsi.service loaded active exited Login and scanning of iSC+
kmod-static-nodes.service loaded active exited Create list of required s+
libvirtd.service loaded active running Virtualization daemon
nscd.service loaded active running Name Service Cache Daemon
chronyd.service loaded active running NTP Server Daemon
polkit.service loaded active running Authorization Manager
postfix.service loaded active running Postfix Mail Transport Ag+
rc-local.service loaded active exited /etc/init.d/boot.local Co+
rsyslog.service loaded active running System Logging Service
[...]
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
161 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.要将输出限制为启动失败的服务,请使用 --failed 选项
# systemctl --failed
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
apache2.service loaded failed failed apache
NetworkManager.service loaded failed failed Network Manager
plymouth-start.service loaded failed failed Show Plymouth Boot Screen
[...]要调试系统启动时间,systemd 提供了 systemd-analyze 命令。它显示总启动时间、按启动时间排序的服务列表,还可以生成 SVG 图形,显示服务启动时间与其他服务之间的关系。
# systemd-analyze
Startup finished in 2666ms (kernel) + 21961ms (userspace) = 24628ms# systemd-analyze blame
15.000s backup-rpmdb.service
14.879s mandb.service
7.646s backup-sysconfig.service
4.940s postfix.service
4.921s logrotate.service
4.640s libvirtd.service
4.519s display-manager.service
3.921s btrfsmaintenance-refresh.service
3.466s lvm2-monitor.service
2.774s plymouth-quit-wait.service
2.591s firewalld.service
2.137s initrd-switch-root.service
1.954s ModemManager.service
1.528s rsyslog.service
1.378s apparmor.service
[...]# systemd-analyze plot > jupiter.example.com-startup.svg上述命令列出启动的服务及其启动时间。要获得更详细的概述,请在启动提示符处指定以下参数,以指示 systemd 创建完整的启动过程的详细日志。
systemd.log_level=debug systemd.log_target=kmsg
现在 systemd 将其日志消息写入内核环形缓冲区。使用 dmesg 查看该缓冲区
> dmesg -T | less
systemd 与 System V 兼容,允许您继续使用现有的 System V init 脚本。但是,已知至少存在一个问题,即 System V init 脚本在不进行任何修改的情况下无法与 systemd 一起工作:通过 su 或 sudo 在 init 脚本中以不同用户身份启动服务会导致脚本失败,产生““访问被拒绝””错误。
在使用 su 或 sudo 更改用户时,将启动 PAM 会话。该会话将在 init 脚本完成后终止。因此,由 init 脚本启动的服务也会终止。要解决此错误,请按以下步骤操作
创建一个服务文件包装器,其名称与 init 脚本相同,并带有文件扩展名 .service
[Unit] Description=DESCRIPTION After=network.target [Service] User=USER Type=forking1 PIDFile=PATH TO PID FILE1 ExecStart=PATH TO INIT SCRIPT start ExecStop=PATH TO INIT SCRIPT stop ExecStopPost=/usr/bin/rm -f PATH TO PID FILE1 [Install] WantedBy=multi-user.target2
将所有大写字母的值替换为适当的值。
使用 systemctl start APPLICATION 启动守护程序。
基本的服务管理也可以使用 YaST 服务管理器模块完成。它支持启动、停止、启用和禁用服务。它还允许您显示服务状态和更改默认目标。使用 › › 启动 YaST 模块。
要更改系统启动的目标,请从 下拉框中选择一个目标。最常用的目标是 (启动图形登录屏幕)和 (以命令行模式启动系统)。
从表中选择一个服务。 列显示它当前是否正在运行()或未运行()。通过选择 或 来切换其状态。
启动或停止服务会更改当前会话中的服务状态。要更改重新启动时的状态,需要启用或禁用它。
服务可以自动在启动时启动,也可以手动启动。从表中选择一个服务。 列显示它当前是 启动还是 。通过选择 来切换其状态。
要更改当前会话中的服务状态,需要按照上述描述启动或停止它。
要查看服务的状态消息,请从列表中选择它并选择 。输出与命令 systemctl -l status MY_SERVICE 生成的输出相同。
systemd #Edit source以下部分介绍了如何自定义 systemd 单元文件。
SUSE 提供的 systemd 单元文件存储在 /usr/lib/systemd/ 中。自定义单元文件和单元文件 drop-ins 存储在 /etc/systemd/ 中。
自定义 systemd 时,始终使用目录 /etc/systemd/ 而不是 /usr/lib/systemd/。否则,您的更改将在下一次更新 systemd 时被覆盖。
Drop-in 文件(或 drop-ins)是部分单元文件,仅覆盖单元文件的特定设置。Drop-in 具有比主配置文件更高的优先级。命令 systemctl edit SERVICE 启动默认文本编辑器,并在 /etc/systemd/system/NAME.service.d/ 中创建一个带有空 override.conf 文件的目录。该命令还会确保正在运行的 systemd 进程收到更改通知。
例如,要更改系统等待 MariaDB 启动的时间量,请运行 sudo systemctl edit mariadb.service 并编辑打开的文件以仅包含修改后的行
# Configures the time to wait for start-up/stop TimeoutSec=300
调整 TimeoutSec 值并保存更改。要启用更改,请运行 sudo systemctl daemon-reload。
有关更多信息,请参阅可以使用命令 man 1 systemctl 调用的手册页。
如果使用 --full 选项在 systemctl edit --full SERVICE 命令中,将创建原始单元文件的副本,您可以在其中修改特定选项。我们不建议进行此类自定义,因为当 SUSE 更新单元文件时,其更改会被 /etc/systemd/system/ 目录中的自定义副本覆盖。此外,如果 SUSE 提供对分发 drop-in 的更新,它们会覆盖使用 --full 创建的单元文件副本。为了防止混淆并始终使您的自定义有效,请使用 drop-in。
除了使用 systemctl edit 命令之外,您还可以手动创建 drop-in 文件以更好地控制其优先级。此类 drop-in 允许您扩展单元和守护程序配置文件,而无需编辑或覆盖文件本身。它们存储在以下目录中
/etc/systemd/*.conf.d/, /etc/systemd/system/*.service.d/由系统管理员添加和自定义的 drop-in。
/usr/lib/systemd/*.conf.d/, /usr/lib/systemd/system/*.service.d/由自定义包安装以覆盖上游设置的 drop-in。例如,SUSE 提供了 systemd-default-settings。
请参阅可以使用命令 man 5 systemd.unit 调用的手册页,以获取完整的单元搜索路径列表。
例如,要禁用默认设置强制执行的 systemd-journald 的速率限制,请执行以下步骤
在 /etc/systemd/journald.conf.d 中创建一个名为 /etc/systemd/journald.conf.d 的目录。
>sudomkdir /etc/systemd/journald.conf.d
目录名称必须遵循您想要使用 drop-in 文件修补的服务名称。
在该目录下,创建一个文件 /etc/systemd/journald.conf.d/60-rate-limit.conf,其中包含您想要覆盖的选项,例如
>cat /etc/systemd/journald.conf.d/60-rate-limit.conf# Disable rate limiting RateLimitIntervalSec=0
保存您的更改并重启相应的 systemd 守护进程的服务。
>sudosystemctl restart systemd-journald
为了避免您的 drop-in 文件与 SUSE 提供的文件之间的名称冲突,建议将所有 drop-in 文件都以两位数字和破折号作为前缀,例如 80-override.conf。
以下范围已保留
0-19 保留给 systemd 上游。
20-29 保留给 SUSE 提供的 systemd。
30-39 保留给 SUSE 除了 systemd 之外的其他软件包。
40-49 保留给第三方软件包。
50 保留给使用 systemctl set-property 创建的单元 drop-in 文件。
使用高于此范围的两位数字,以确保 SUSE 提供的任何 drop-in 文件都无法覆盖您自己的 drop-in 文件。
您可以使用 systemctl cat $UNIT 来列出并验证哪些文件被纳入单元配置中。
由于 systemd 组件的配置可能分散在文件系统中的不同位置,因此很难获得全局概览。要检查 systemd 组件的配置,请使用以下命令
systemctl cat UNIT_PATTERN 打印与一个或多个 systemd 单元相关的配置文件,例如
> systemctl cat atd.service
systemd-analyze cat-config DAEMON_NAME_OR_PATH 复制 systemd 守护进程的配置文件的内容和 drop-in 文件,例如
> systemd-analyze cat-config systemd/journald.conf自 openSUSE Leap 15 发布以来,xinetd 基础设施已被移除。本节概述了如何将现有的自定义 xinetd 服务文件转换为 systemd sockets。
对于每个 xinetd 服务文件,您至少需要两个 systemd 单元文件:socket 文件 (*.socket) 和关联的服务文件 (*.service)。socket 文件告诉 systemd 创建哪个 socket,而服务文件告诉 systemd 启动哪个可执行文件。
考虑以下示例 xinetd 服务文件
# cat /etc/xinetd.d/example
service example
{
socket_type = stream
protocol = tcp
port = 10085
wait = no
user = user
group = users
groups = yes
server = /usr/libexec/example/exampled
server_args = -auth=bsdtcp exampledump
disable = no
}要将其转换为 systemd,您需要以下两个匹配的文件
# cat /usr/lib/systemd/system/example.socket
[Socket]
ListenStream=0.0.0.0:10085
Accept=false
[Install]
WantedBy=sockets.target# cat /usr/lib/systemd/system/example.service
[Unit]
Description=example
[Service]
ExecStart=/usr/libexec/example/exampled -auth=bsdtcp exampledump
User=user
Group=users
StandardInput=socket有关 systemd “socket” 和 “service” 文件选项的完整列表,请参阅 systemd.socket 和 systemd.service 手册页 (man 5 systemd.socket, man 5 systemd.service)。
在 System V init SUSE 系统上,runlevel 4 未被使用,以允许管理员创建自己的 runlevel 配置。 systemd 允许您创建任意数量的自定义目标。建议从调整现有的目标开始,例如 graphical.target。
将配置文件 /usr/lib/systemd/system/graphical.target 复制到 /etc/systemd/system/MY_TARGET.target 并根据您的需要进行调整。
在上一步中复制的配置文件已经涵盖了目标的必需(““hard””)依赖项。要同时涵盖所需的(““soft””)依赖项,请创建一个目录 /etc/systemd/system/MY_TARGET.target.wants。
对于每个所需的服务,请从 /usr/lib/systemd/system 创建一个符号链接到 /etc/systemd/system/MY_TARGET.target.wants。
完成目标的设置后,重新加载 systemd 配置以使新的目标可用
>sudosystemctl daemon-reload
以下部分涵盖了系统管理员的高级主题。有关更高级的 systemd 文档,请参阅 Lennart Pöttering 关于 systemd 的管理员系列文章,网址为 https://0pointer.de/blog/projects/。
systemd 支持定期清理临时目录。以前版本的配置会自动迁移并处于活动状态。 tmpfiles.d—负责管理临时文件—从 /etc/tmpfiles.d/*.conf、/run/tmpfiles.d/*.conf 和 /usr/lib/tmpfiles.d/*.conf 文件读取其配置。放置在 /etc/tmpfiles.d/*.conf 中的配置会覆盖来自其他两个目录的相关配置(/usr/lib/tmpfiles.d/*.conf 是软件包存储其配置文件的地方)。
配置格式是每行一个路径,包含操作和路径,以及可选的模式、所有权、年龄和参数字段,具体取决于操作。以下示例取消链接 X11 锁文件
Type Path Mode UID GID Age Argument r /tmp/.X[0-9]*-lock
要获取 tmpfile 定时器的状态
>sudosystemctl status systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static) Active: active (waiting) since Tue 2018-04-09 15:30:36 CEST; 1 weeks 6 days ago Docs: man:tmpfiles.d(5) man:systemd-tmpfiles(8) Apr 09 15:30:36 jupiter systemd[1]: Starting Daily Cleanup of Temporary Directories. Apr 09 15:30:36 jupiter systemd[1]: Started Daily Cleanup of Temporary Directories.
有关临时文件处理的更多信息,请参阅 man 5 tmpfiles.d。
第 10.6.9 节,“调试服务” 解释了如何查看给定服务的日志消息。但是,显示日志消息不限于服务日志。您还可以访问和查询 systemd 写入的完整日志消息—所谓的““Journal””。使用命令 journalctl 显示完整的日志消息,从最早的条目开始。有关应用过滤器或更改输出格式等选项,请参阅 man 1 journalctl。
您可以将 systemd 的当前状态保存到命名快照中,稍后可以使用 isolate 子命令恢复到它。这在测试服务或自定义目标时很有用,因为它允许您随时返回到定义的狀態。快照仅在当前会话中可用,并在重新启动时自动删除。快照名称必须以 .snapshot 结尾。
>sudosystemctl snapshot MY_SNAPSHOT.snapshot
>sudosystemctl delete MY_SNAPSHOT.snapshot
>sudosystemctl show MY_SNAPSHOT.snapshot
>sudosystemctl isolate MY_SNAPSHOT.snapshot
使用 systemd,内核模块可以在启动时通过 /etc/modules-load.d 中的配置文件自动加载。该文件应命名为 MODULE.conf 并且具有以下内容
# load module MODULE at boot time MODULE
如果软件包安装了用于加载内核模块的配置文件,则该文件将安装到 /usr/lib/modules-load.d。如果存在两个名称相同的配置文件,则 /etc/modules-load.d 中的文件优先。
有关更多信息,请参阅 modules-load.d(5) 手册页。
使用 System V init,需要在 /etc/init.d/before.local 中指定的在加载服务之前需要执行的操作。此过程不再受 systemd 支持。如果您需要执行操作,请执行以下操作
在 /etc/modules-load.d 目录中创建一个 drop-in 文件(有关语法,请参阅 man modules-load.d)
在 /etc/tmpfiles.d 中创建一个 drop-in 文件(有关语法,请参阅 man tmpfiles.d)
从以下模板在 /etc/systemd/system/before.service 创建一个系统服务文件
[Unit] Before=NAME OF THE SERVICE YOU WANT THIS SERVICE TO BE STARTED BEFORE [Service] Type=oneshot RemainAfterExit=true ExecStart=YOUR_COMMAND # beware, executable is run directly, not through a shell, check the man pages # systemd.service and systemd.unit for full syntax [Install] # target in which to start the service WantedBy=multi-user.target #WantedBy=graphical.target
创建服务文件后,您应该运行以下命令(以 root 身份)
>sudosystemctl daemon-reload>sudosystemctl enable before
每次修改服务文件时,都需要运行
>sudosystemctl daemon-reload
在传统的 System V init 系统上,有时无法将进程与生成它的服务匹配。某些服务(例如 Apache)会生成许多第三方进程(例如 CGI 或 Java 进程),这些进程本身又会生成更多进程。这使得清晰的分配变得困难甚至不可能。此外,服务可能无法正确完成,留下某些子进程处于活动状态。
systemd 通过将每个服务放入自己的 cgroup 来解决此问题。cgroups 是内核功能,允许将进程及其所有子进程聚合到分层组织的组中。 systemd 根据其服务命名每个 cgroup。由于非特权进程不允许““离开””其 cgroup,因此这提供了一种有效地使用服务名称标记服务生成的所有进程的方法。
要列出属于服务的进程,请使用命令 systemd-cgls,例如
# systemd-cgls --no-pager
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
├─user.slice
│ └─user-1000.slice
│ ├─session-102.scope
│ │ ├─12426 gdm-session-worker [pam/gdm-password]
│ │ ├─15831 gdm-session-worker [pam/gdm-password]
│ │ ├─15839 gdm-session-worker [pam/gdm-password]
│ │ ├─15858 /usr/lib/gnome-terminal-server
[...]
└─system.slice
├─systemd-hostnamed.service
│ └─17616 /usr/lib/systemd/systemd-hostnamed
├─cron.service
│ └─1689 /usr/sbin/cron -n
├─postfix.service
│ ├─ 1676 /usr/lib/postfix/master -w
│ ├─ 1679 qmgr -l -t fifo -u
│ └─15590 pickup -l -t fifo -u
├─sshd.service
│ └─1436 /usr/sbin/sshd -D
[...]有关 cgroups 的更多信息,请参阅 “系统分析和调优指南”书籍,第 10 章“内核控制组”。
如 第 10.6.6 节,“内核控制组 (cgroups)” 所述,在 System V init 系统中,有时无法将进程分配给其父服务进程。这使得停止服务及其子进程变得困难。未终止的子进程仍然是僵尸进程。
systemd 将每个服务限制到 cgroup 的概念使得能够识别服务的子进程,因此允许您将信号发送到这些进程中的每一个。使用 systemctl kill 向服务发送信号。有关可用信号的列表,请参阅 man 7 signals。
SIGTERM
SIGTERM 是默认发送的信号。
>sudosystemctl kill MY_SERVICE
使用 -s 选项指定要发送的信号。
>sudosystemctl kill -s SIGNAL MY_SERVICE
默认情况下,kill 命令将信号发送到指定 cgroup 的 all 进程。您可以将其限制为 control 或 main 进程。后者例如对于通过发送 SIGHUP 强制服务重新加载其配置很有用
>sudosystemctl kill -s SIGHUP --kill-who=main MY_SERVICE
D-Bus 服务是 systemd 客户端与作为 pid 1 运行的 systemd 管理器之间通信的消息总线。即使 dbus 是一个独立的守护进程,但它也是 init 基础设施不可或缺的一部分。
停止 dbus 或在运行系统中重新启动它类似于尝试停止或重新启动 PID 1。它破坏了 systemd 客户端/服务器通信,并使大多数 systemd 功能无法使用。
因此,不建议也不支持终止或重新启动 dbus。
更新 dbus 或 dbus 相关软件包需要重新启动。如果不确定是否需要重新启动,请运行 sudo zypper ps -s。如果 dbus 出现在列出的服务中,则需要重新启动系统。
请记住,即使自动更新配置为跳过需要重新启动的软件包,dbus 也会更新。
默认情况下,systemd 并非过于冗长。如果服务启动成功,则不会产生任何输出。如果发生故障,将显示一条简短的错误消息。但是,systemctl status 提供了一种调试服务启动和运行的方式。
systemd 带有自己的日志记录机制(““日志””),用于记录系统消息。这允许您将服务消息与状态消息一起显示。 status 命令的工作方式类似于 tail,并且还可以以不同的格式显示日志消息,使其成为一个强大的调试工具。
每当服务启动失败时,使用 systemctl status MY_SERVICE 获取详细的错误消息
#systemctl start apache2 Job failed. See system journal and 'systemctl status' for details.#systemctl status apache2 Loaded: loaded (/usr/lib/systemd/system/apache2.service; disabled) Active: failed (Result: exit-code) since Mon, 04 Apr 2018 16:52:26 +0200; 29s ago Process: 3088 ExecStart=/usr/sbin/start_apache2 -D SYSTEMD -k start (code=exited, status=1/FAILURE) CGroup: name=systemd:/system/apache2.service Apr 04 16:52:26 g144 start_apache2[3088]: httpd2-prefork: Syntax error on line 205 of /etc/apache2/httpd.conf: Syntax error on li...alHost>
status 子命令的默认行为是显示服务发出的最后十条消息。要更改要显示的消息数量,请使用 --lines=N 参数
>sudosystemctl status chronyd>sudosystemctl --lines=20 status chronyd
要显示服务的““实时流””消息,请使用 --follow 选项,该选项类似于 tail -f
>sudosystemctl --follow status chronyd
--output=MODE 参数允许您更改服务消息的输出格式。最重要的可用模式是
short默认格式。以人类可读的时间戳显示日志消息。
verbose包含所有字段的完整输出。
cat简洁的输出,没有时间戳。
与 cron 类似,systemd 定时器单元提供了一种在 Linux 上调度作业的机制。虽然 systemd 定时器单元与 cron 具有相同的目的,但它们提供了几个优势。
使用定时器单元调度的作业可以依赖于其他 systemd 服务。
定时器单元被视为常规 systemd 服务,因此可以使用 systemctl 进行管理。
定时器可以是实时和单调的。
时间单元被记录到 systemd 日志中,这使得更容易监控和排除故障。
systemd 定时器单元由 .timer 文件名扩展名标识。
定时器单元可以使用单调和实时定时器。
与 cron 作业类似,实时定时器由日历事件触发。实时定时器使用 OnCalendar 选项定义。
单调定时器在从某个起始点经过指定时间后触发。后者可以是系统启动或系统单元激活事件。有几个选项可以定义单调定时器,包括 OnBootSec、OnUnitActiveSec 和 OnTypeSec。单调定时器不是持久性的,并且在每次重新启动后都会重置。
每个定时器单元都必须有一个对应的 systemd 单元文件来控制它。换句话说,一个 .timer 文件激活和管理相应的 .service 文件。与定时器一起使用时,.service 文件不需要 [Install] 部分,因为服务由定时器管理。
要了解 systemd 定时器单元的基础知识,我们设置一个定时器来触发 foo.sh shell 脚本。
第一步是创建一个 systemd 服务单元来控制 shell 脚本。为此,打开一个新文本文件进行编辑,并添加以下服务单元定义
[Unit] Description="Foo shell script" [Service] ExecStart=/usr/local/bin/foo.sh
将文件保存为 foo.service,并将其放在 /etc/systemd/system/ 目录中。
接下来,打开一个新文本文件进行编辑,并添加以下定时器定义
[Unit] Description="Run foo shell script" [Timer] OnBootSec=5min OnUnitActiveSec=24h Unit=foo.service [Install] WantedBy=multi-user.target
上述示例中的 [Timer] 部分指定要触发的服务(foo.service)以及何时触发它。在这种情况下,OnBootSec 选项指定一个单调定时器,该定时器在系统启动后五分钟触发服务,而 OnUnitActiveSec 选项在服务激活后 24 小时触发服务(即,定时器每天触发服务一次)。最后,WantedBy 选项指定定时器应在系统达到多用户目标时启动。
您可以指定实时定时器,而不是使用 OnCalendar 选项。以下实时定时器定义每周触发一次相关服务,从周一中午 12:00 开始。
[Timer] OnCalendar=weekly Persistent=true
Persistent=true 选项指示如果定时器错过了上次启动时间(例如,因为系统已关机),则在定时器激活后立即触发服务。
OnCalendar 选项还可以用于使用以下格式定义触发服务的特定日期时间:DayOfWeek Year-Month-Day Hour:Minute:Second。以下示例每天凌晨 5 点触发服务
OnCalendar=*-*-* 5:00:00
您可以使用星号指定任何值,并使用逗号列出可能的值。使用两个值,用 .. 分隔,表示一个连续的范围。以下示例每月 19 点触发服务
OnCalendar=Fri *-*-1..7 18:00:00
要以不同的时间触发服务,您可以指定多个 OnCalendar 条目
OnCalendar=Mon..Fri 10:00 OnCalendar=Sat,Sun 22:00
在上面的示例中,服务在工作日早上 10 点触发,在周末晚上 10 点触发。
完成编辑定时器单元文件后,将其保存为 foo.timer,并将其放在 /etc/systemd/system/ 目录中。要检查创建的单元文件的正确性,请运行以下命令
>sudosystemd-analyze verify /etc/systemd/system/foo.*
如果该命令没有返回任何输出,则文件已通过验证。
要启动定时器,请使用命令 sudo systemctl start foo.timer。要在启动时启用定时器,请运行命令 sudo systemctl enable foo.timer。
有关 systemd 的更多信息,请参阅以下在线资源
systemd 管理员Lennart Pöttering,systemd 的作者之一,写了一系列博客文章(在撰写本章时为 13 篇)。在 https://0pointer.de/blog/projects/ 找到它们。