【问题标题】:How to restart a service if its dependent service is restarted如果重新启动其依赖服务,如何重新启动服务
【发布时间】:2016-07-02 19:43:44
【问题描述】:

一个服务(比如 bar.service)依赖于另一个服务(比如 foo.service),如下所示

酒吧的服务文件:

[Unit]
After=foo.service
Requires=foo.service
...

如果 foo.service 重新启动(手动或由于错误),如何自动重新启动 bar.service?

【问题讨论】:

  • 您是否尝试在您的服务中添加“Restart=always”行?我猜 bar 应该在它的依赖项存在后立即重新启动
  • @SnP Restart "配置是否在服务进程退出、被杀死或达到超时时重新启动服务",因此除非 foo 重新启动时 bar 崩溃,否则将无济于事。
  • 很有趣!感谢您的澄清

标签: linux systemd


【解决方案1】:

您可以使用PartOf

[Unit]
After=foo.service
Requires=foo.service
PartOf=foo.service

来自systemd.unit 手册页:

部分=

配置与 Requires= 类似的依赖项,但仅限于停止和重新启动单元。当 systemd 停止或重新启动此处列出的单元时,该操作将传播到该单元。请注意,这是一种单向依赖——对此单位的更改不会影响列出的单位。

【讨论】:

  • 请注意,PartOf 仅链接重新启动,但不链接停止、升级、启动事件。在这些情况下,您可能需要WantedBySee this answer for details
  • 它不链接停止事件?它在上面的定义中说了两次:When systemd stops or restarts the units listed here, the action is propagated to this unit
  • @jdizzle 文档可以随便写,行为明显不同。我试了一下。依赖服务使用 foo 重新启动,但如果 foo 之前显式停止,它不会在 foo 之后启动。它只是保持停止。所以PartOf 适合 foo 的自动更新或配置更新,仅此而已。
  • @ygoe 是的,它只链接停止和重新启动。不开始。为此,您需要WantsRequires
【解决方案2】:

另一种解决方案可能是在 foo.service 已(重新)启动时使用 ExecStartPost 选项重新启动 bar.service(如果已执行):

# foo.service
[Service]
ExecStartPost=/bin/systemctl try-restart bar.service
Restart=on-failure
RestartSec=30s

额外的 RestartRestartSec 选项确保 foo.service 将在崩溃时自动重启,因此 bar.service 也将自动重启。

第二个扩展可以添加到 bar.service 并确保 bar.service 在 foo.service 之后启动:

# bar.service
[Unit]
After=foo.service

[Service]
Restart=on-failure
RestartSec=30s

这应该会在崩溃的情况下自动启动两个服务,并且 bar.service 将在 foo.service 重新启动时重新启动(由于错误或手动触发)。

【讨论】:

    【解决方案3】:

    我认为需要的选项是 BindsTo,它也可以处理不当行为。

    [Unit]
    Requires=postgresql.service
    After=postgresql.service
    BindsTo=postgresql.service
    

    绑定到=

    配置需求依赖,风格与Requires=非常相似。但是,这种依赖类型更强:除了 Requires= 的效果外,它还声明如果绑定到的单元停止,则该单元也将停止。这意味着绑定到另一个单元的单元突然进入非活动状态也将被停止。单元可能由于不同的原因突然、意外地进入非活动状态:服务单元的主进程可能会自行终止,设备单元的后备设备可能已拔出,或者挂载单元的挂载点可能会在没有参与的情况下被卸载系统和服务管理器。

    当在同一单元上与 After= 结合使用时,BindsTo= 的行为会更加强大。在这种情况下,严格绑定到的单元必须处于活动状态才能使该单元也处于活动状态。这不仅意味着一个绑定到另一个突然进入非活动状态的单元的单元,而且还意味着一个绑定到另一个由于条件检查失败而被跳过的单元(例如 ConditionPathExists=、ConditionPathIsSymbolicLink=、... — 见下文)将是停止,它应该正在运行。因此,在许多情况下,最好将 BindsTo= 与 After= 结合使用。

    【讨论】:

    • 我的经验是,使用 BindsTo 时设备不会重新启动。它只会停止。但是当使用 PartOf 时,它确实停止并重新启动。
    • 然而,正如@Rennex 指出的那样,开始需要在[Install] 中有WantedBy=foo.service 指令
    • @BrnVm WantedBy 是另一个依赖项。您的 MyService 不是 Postgres 的依赖项,但不是。每当启动 Postgres 时,我都不想启动 MyService。我只想在 Postgres 死机或重新启动时重新启动 MyService。 Requires 和 After 处理对 Postgres 和 BindsTo 的依赖关系重启 MyService。
    猜你喜欢
    • 2015-10-28
    • 1970-01-01
    • 2017-12-29
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    相关资源
    最近更新 更多