重启信号对 systemd 服务状态的影响

sco*_*eus 5 systemd services

我目前正在使用systemd服务。什么是国家的序列变化,当,例如,所有的服务承诺init 6rebootinit 0执行?

这是我产生这个问题的场景:

我有一项A旨在在关机和重新启动时激活的服务。它意味着从另一个服务 service 调用检索信息BB旨在在启动时激活并连续运行。

reboot或被init 0执行时,可以A期望在哪个状态下找到B

我发现关于这个主题的这段很有趣,但它没有详细说明。

ActiveState 包含一个反映单元当前是否处于活动状态的状态值。当前定义了以下状态:活动、重新加载、非活动、失败、激活、停用。active 表示单元处于活动状态(显然......)。reloading 表示该单元处于活动状态并且当前正在重新加载其配置。inactive 表示它处于非活动状态并且上次运行成功或上次运行尚未发生。failed 表示它处于非活动状态并且上次运行未成功(有关此原因的更多信息可在特定于单元类型的接口上获得,例如对于 Resultproperty 中的服务,请参见下文)。激活表示该单元之前一直处于非活动状态,但当前正处于进入活动状态的过程中。

http://www.freedesktop.org/wiki/Software/systemd/dbus/

int*_*lfx 14

在 systemd 设置中rebootpoweroffhaltinit N都转换为systemctl. systemctl从现在开始,我将谈论。

那么,当您发出(例如)systemctl reboot命令时会发生什么?除了polkit/logind 抽象层(在 root 权限可用时无论如何都不会使用),此命令转换为systemctl isolate reboot.target,而这又等效于systemctl start --job-mode=isolate reboot.target.

在 systemd 的说法中,“隔离”一个单元(无论是目标、服务还是其他任何东西)意味着启动(激活)给定单元及其所有依赖项,并停止(停用)所有其他单元,除非它们已IgnoreOnIsolate=yes指定. 因此,当您发出重新启动命令时,reboot.target(及其 deps)排队启动,所有其他单元排队停止。

我们不会手动检查这些目标的依赖关系(尽管可以使用systemctl list-dependencies命令)。让我们来看看bootup(7),这是一个手册页,描述了 systemd 控制的系统启动/关闭时会发生什么。

相应的 ASCII 图表复制粘贴到此处(FTR,它反映了 systemd 221)。

                              (conflicts with  (conflicts with
                                all system     all file system
                                 services)     mounts, swaps,
                                     |           cryptsetup
                                     |          devices, ...)
                                     |                |
                                     v                v
                              shutdown.target    umount.target
                                     |                |
                                     \_______   ______/
                                             \ /
                                              v
                                     (various low-level
                                          services)
                                              |
                                              v
                                        final.target
                                              |
        _____________________________________/ \_________________________________
       /                         |                        |                      \
       |                         |                        |                      |
       v                         v                        v                      v
systemd-reboot.service   systemd-poweroff.service   systemd-halt.service   systemd-kexec.service
       |                         |                        |                      |
       v                         v                        v                      v
reboot.target             poweroff.target            halt.target           kexec.target
Run Code Online (Sandbox Code Playgroud)

该计划是不言自明的。shutdown.target默认情况下,特殊目标与所有服务单元冲突(除非它们已DefaultDependencies=no设置)。

因此,第一种方法是使您的A服务成为 的依赖项shutdown.target,以便在所有关闭时激活它。(请注意,这也需要制作它DefaultDependencies=no。)

但是,默认情况下,systemd 中的所有内容都是并行完成的,因此您的A服务也需要针对B- 延迟关闭,B直到A启动并完成其数据检索。在systemd.unit(5) 中,我们可以阅读:

如果一个对另一个单元具有排序依赖关系的单元在另一单元启动时关闭,则无论排序依赖项实际上是 After= 还是 Before= 类型,都会在启动之前下令关闭。

这是不幸的:无论我们是让 AAfter=B.service还是Before=B.service,B 都会A 启动之前停止。

所以,我们必须走另一条路。我们可以创建一个正常的 服务Type=oneshot,它/bin/true在激活时什么都不做 ( ),但在停用时做任何需要的事情。(这也需要 make it RemainsAfterExit=yes,否则服务会在/bin/true退出时自动标记为非活动状态。)可以B.service根据需要订购此类服务:

请注意,当两个具有顺序相关性的单元关闭时,将应用启动顺序的倒数。即,如果一个单元在另一个单元上配置了 After=,如果两者都关闭,则前者在后者之前停止。

把这些放在一起,一个单元文件A.service看起来像这样:

[Unit]
Description=Collect information about B

# we want to deactivate together with B
Requisite=B.service

# we want to deactivate before B deactivates
After=B.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecStop=/path/to/B

[Install]
# replace with whatever is needed
WantedBy=B.service
Run Code Online (Sandbox Code Playgroud)

另请注意,如果使用了相当新的 (?217) 版本的 systemd,则ExecStart=/bin/true 可能会被完全排除在外

进一步阅读

  1. systemd(1)手册页,“概念”部分。
  2. systemd.unit(5)手册页,“[Unit] Section Options”部分。
  3. bootup(7)手册页。
  4. systemd.special(5)手册页。