需要共同初始化阶段的 systemd 服务集?

需要共同初始化阶段的 systemd 服务集?

在 systemd 中,我需要设置一些服务,这些服务依赖于一个公共的“初始化”服务,这些服务必须在启动之前完成。此外,我想确保工作服务和“初始化”服务能够任何时候都不会同时运行

                                    manual
    BOOT --.                     "restart svc" ---.
           V                                      V
svc-init   |-----|                                |---------|
svc-a            |--------------------------------|         |----- - - -
svc-b            |--------------------------------|         |----- - - -

我想确保服务已“启用”(在系统启动时运行);此外,我希望能够在需要时随时手动重新启动整个系统。

我怎样才能做到这一点?

我尝试了包含如下重要字段的设置:

/etc/systemd/system/svc-init.service

[Service]
Type=oneshot
ExecStart=/opt/svc/init-svc.sh

[Install]
WantedBy=multi-user.target

.../svc-a.服务.../svc-b.服务

[Unit]
Wants=svc-init.service
After=svc-init.service
Conflicts=svc-init.service

[Service]
Restart=always
ExecStart=/opt/svc/svc.sh

[Install]
WantedBy=multi-user.target

但是当我尝试运行它们时,它无法实现我想要的效果:

  1. sudo systemctl start svc-init
    • 它正确地停止了 svc-a 和 svc-b
    • 但它没有开始svc-init 完成后再次执行 svc-a & svc-b
  2. sudo systemctl start svc-a
    • 它不会强制 svc-init 预先运行
  3. sudo systemctl start svc-a svc-b svc-init
    • 效果似乎与上面的 (1) 相同(即... start svc-init
  4. sudo systemctl start svc-init svc-a svc-b
    • 不运行 svc-init
    • 印刷:Job for svc-init.service canceled.

有什么神奇的 systemd 命令可以让系统按照我需要的方式运行?或者我应该以某种方式以不同的方式构建单元?

编辑:根据评论中的建议:澄清一下,在我看来,svc-a 和 svc-b 实际上是一个服务的实例,可能需要动态启动/停止(它们实际上是:svc@1,,,等等)。svc@2svc@3

答案1

Systemd 可能很难推理,但这似乎是一个值得尝试的好实验:

服务初始化

[Unit]
[email protected]

Before告诉 systemd svc-init 需要先完成所有操作,然后才能启动任何命名服务。这应该会为您提供明确的必须完成顺序。

[电子邮件保护]

[Unit]
After=svc-init.service
BindsTo=svc-init.service

After模仿Beforesvc-init 服务中的,可能对您来说更方便。在两个地方声明它不是错误,也不是必需的。它只是明确了您的意图。

BindsTo告诉 systemd,如果指定的服务因任何原因停止,则此服务也会停止。将其与AfterBefore声明一起使用可确保此停止以正确的顺序进行。根据您的需要,您可能希望使用Requires而不是BindsTo,因为Requires表示仅当指定服务明确地已停止。如果BindsTo使用,则每当svc-init重新启动时,此服务也将重新启动。这两个版本都是Wants您在例子中列出。

按照这样的配置,当svc-init从停止状态启动时,它将等待svc直到启动完成后才触发任何实例svc-init(Before/After),并且只有在成功完成启动(BindsTo)后才会触发svc-init。完成后,svc将启动任何实例。如果svc-init给定停止命令,所有svc实例将同时停止svc-init(BindsTo)。如果svc-init给定重新开始命令后,svc-init 及其相关服务将停止然后启动。

如果svc-init打算启动然后退出,您可能需要SuccessExitStatus=在其Unit部分中进行声明以告诉 systemd 在成功启动时需要哪些退出代码。

答案2

假设你不能摆脱脚本,让 systemd 自己完成所有的设置(你几乎肯定可以,但编写脚本的人可能不知道怎么做;向供应商/开发商大喊大叫,直到他们学会为止),我认为你应该只使用为此的单元文件。

在单个单元文件中,你将在ExecStartPre=选项。如果此处调用的程序无法成功退出,则单元将无法启动。例如,在[email protected]

[Service]
Restart=always
ExecStartPre=/opt/svc/init-svc.sh %I
ExecStart=/opt/svc/svc.sh %I

[Install]
WantedBy=multi-user.target

相关内容