进一步阅读

进一步阅读

systemd目前正在从事服务工作。例如,当执行init 6reboot或 时,所有服务进行的状态更改的顺序是什么?init 0

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

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

rebootinit 0被执行时,可以在哪个状态A下找到B

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

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

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

答案1

在 systemd 设置中,rebootpoweroff和allhaltinit N转换为以下的各种子命令systemctl。我systemctl将从现在开始谈论。

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

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

我们不会手动检查这些目标的依赖关系(尽管可以使用systemctl list-dependencies命令)。让我们看看启动(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

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

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

然而,默认情况下,systemd 中的所有事情都是并行完成的,因此您的A服务也需要进行排序B- 延迟关闭,B直到A启动并完成其数据检索。在系统单元(5)我们可以读到:

如果一个单元与另一个单元有顺序依赖性,而后者在启动时被关闭,则关闭将在启动之前进行,无论顺序依赖性实际上是 After= 还是 Before= 类型。

这是不幸的:无论我们做AAfter=B.service还是做Before=B.serviceB,都会被阻止A开始了。

所以,我们必须走另一条路。我们可以创建一个普通的 服务Type=oneshot,它在激活时不执行任何操作 ( /bin/true),但在停用时执行所需的任何操作。 (这也需要进行设置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

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

进一步阅读

  1. 系统(1)手册页,“概念”部分。
  2. 系统单元(5)手册页,“[Unit] 部分选项”部分。
  3. 启动(7)手册页。
  4. systemd.特殊(5)手册页。

相关内容