在 systemd 中,After= 和 Requires= 有什么区别?

在 systemd 中,After= 和 Requires= 有什么区别?

Requires=我正在创建一个 systemd .service 文件,我需要帮助理解和之间的区别After=手册页说的是Requires=“配置对其他单元的要求依赖关系。”和After=“配置单元之间的顺序依赖关系。”有什么区别?

答案1

After=配置服务顺序(仅在 Y 之后执行 X),同时Requires=说明依赖关系。

如果您未指定顺序,则依赖于另一个服务的服务将与它所依赖的服务同时启动。

此外,我的理解方式(虽然我现在无法测试并且找不到参考)After=是“松散耦合”,这实际上意味着After即使行中命名的服务After=根本没有启动,带有语句的服务仍会运行,而Requires=如果不满足要求,则会阻止其启动。

引用https://www.freedesktop.org/software/systemd/man/systemd.unit.html

要求=

配置对其他单元的依赖关系。如果此单元被激活,则此处列出的单元也将被激活。如果其他单元之一被停用或激活失败,则此单元将被停用。可以多次指定此选项,也可以在一个选项中指定多个以空格分隔的单元,在这种情况下将创建所有列出名称的依赖关系。请注意,依赖关系不会影响服务启动或停止的顺序。这必须使用 After= 或 Before= 选项单独配置。如果单元 foo.service 需要单元 bar.service(如使用 Requires= 配置的一样),并且未使用 After= 或 Before= 配置任何顺序,则如果 foo.service 被激活,则两个单元将同时启动,并且它们之间没有任何延迟。通常,为了实现在处理失败服务时更强大的系统,使用 Wants= 而不是 Requires= 是更好的选择。

之前=,之后=

以空格分隔的单元名称列表。配置单元之间的顺序依赖关系。如果单元 foo.service 包含设置 Before=bar.service 并且两个单元都在启动,则 bar.service 的启动将延迟到 foo.service 启动。请注意,此设置与 Requires= 配置的需求依赖关系无关且正交。在 After= 和 Requires= 选项中同时包含单元名称是一种常见模式,在这种情况下,列出的单元将在使用这些选项配置的单元之前启动。可以多次指定此选项,在这种情况下将为所有列出的名称创建顺序依赖关系。After= 是 Before= 的逆操作,即,虽然 After= 确保配置的单元在列出的单元完成启动后启动,但 Before= 确保相反,即配置的单元在列出的单元启动之前完全启动。请注意,当两个具有顺序依赖关系的单元关闭时,将应用启动顺序的逆操作。即,如果一个单元在另一个单元上配置了 After=,则如果两个单元都关闭,则前者会先停止,后者会先停止。给定两个之间存在任何顺序依赖关系的单元,如果一个单元关闭而另一个单元启动,则关闭顺序会先于启动。顺序依赖关系是 After= 还是 Before= 并不重要。两者中的哪一个被关闭也不重要,只要一个被关闭而另一个被启动即可。在所有情况下,关闭顺序都会先于启动。如果两个单元之间没有顺序依赖关系,则它们会同时关闭或启动,并且不进行排序。

答案2

其中一个主要区别是,

  • After仅检查单位是否已经激活,并不明确激活指定的单位。
  • 列出的单元Requires与该单元一起激活。如果任何所需单元启动失败,则该单元不会被激活。

假设我有一个单元文件test-app.service

[Unit]
Description=test app
After=network-online.target

执行此语句后将发生以下情况,

  • After检查是否network-online.target
  • network-online.target尚未启动,则等待。
  • test-appnetwork-online.target仅在激活后启动

如果我有的Requires话,

[Unit]
Description=test app
Requires=network-online.target

执行此语句后将发生以下情况,

  • network-online.targettest-app同时激活
  • 如果network-online.target启动失败test-app将不会被激活。

答案3

systemd 是一个作业管理器。手册页没有非常精确地说明其工作原理。

当您启动时,systemd 会构建一个由锚定作业(即启动 default.target 的作业)组成的事务。所有这些依赖关系和关系的作用是定义如何触发作业以及触发哪些作业。顺序定义了其他每个作业将等待哪些作业。因此,default.target 单元是所有这一切的中心,这就是为什么在启用单元时使用反向依赖关系,通过 systemctl enable 创建一个文件系统符号链接,表示 systemd 可以遵循的前向依赖关系(这也是为什么您首先需要文件系统符号链接)。类似的是,当您手动启动某个单元时,该单元就是锚定单元,事务是相对于它计算的。

我不会讲得太详细,我只是解释一下 Requires= 和 After= 的作用。

当您触发启动作业时(明确地,或通过依赖项:内部没有区别),Requires= 将导致 systemd 为所需单元触发启动作业。它还具有在此单元停止(注意:已停止,而不是自行停止)或重新启动时触发停止作业的属性。这意味着如果某个依赖项/systemctl 导致其停止/重新启动,您也将停止/重新启动。但是,如果它自行停止,您将不会停止,因为没有作业,并且状态更改是在没有 systemd 参与的情况下发生的。这就是您将使用 BindsTo= 的地方(类似于设备单元,出于显而易见的原因,它可以在没有 systemd 参与的情况下进入非活动状态)。

现在,建议使用 After=,因为 Requires= 本身就很活跃:如果启动作业失败,则取消所需作业。但是,此取消仅适用于作业,即,如果另一个单元未定义顺序,则 systemd 会并行触发两者,并且如果它的启动作业在您的启动作业失败之前完成,则不会取消它(事实上,它无法取消)。使用 After= 意味着其他作业会一直等待,直到所需单元的启动作业完成,并且根据结果,如果失败,您的单元的等待启动作业将使用 JOB_DEPENDENCY 作业结果取消(为什么在这种情况下在启动时使用黄色 [DEPEND])。因此,如果不使用 After=,这种无效效果是不确定的。

这就是为什么如果您不想等待其他单元的启动,那么使用 Wants= 而不使用 After= 是可以的:因为那里没有无效,所以没有竞争。在这种情况下,它只不过是一种同步机制。

此外,您还可以在启动时启用两者,而不需要彼此,并且仅定义排序,在这种情况下,当两者作为同一事务的一部分被拉取时,它们将被排序(或者如果另一个的作业在它想要运行的单元的作业正在运行时触发,它将首先等待它完成,跨事务)。

现在,如果没有作业,排序对所述单元没有影响。但是,通常会有作业,这是使用依赖项(如 Requires= 和 Wants=)的结果,或者两者同时被拉入并定义某种排序,在这种情况下,它们会等待另一个单元的作业。

答案4

作为补充,主要是对塞巴斯蒂安的回答:

“请注意,需求依赖关系不会影响服务启动或停止的顺序。”

上面有一位用户评论道“如果不是顺序声明,依赖关系是什么?“,我同意。我认为这个说法是半正确的。它应该是:

“请注意,需求依赖关系不会影响精确的服务启动或停止的顺序。”

当然,依赖关系会影响顺序:

  • 如果您有一组七项服务,并且其中一项(且仅一项)依赖于所有其他服务,那么您可以预测该服务将稍后或与其他服务同时启动。

  • 如果这七个服务中有一个服务没有任何依赖关系,但所有其他服务都依赖于它,那么您可以预测该服务将与其他服务更早或同时启动。

Before=After=存在以使那些原本会同时启动(或以随机顺序启动)的服务能够进行启动顺序微调。

如果服务 A 依赖于服务 B,但服务 A 必须在服务 B 之前启动,会发生什么情况?

systemd-analyze verify A.service

会告诉你。

相关内容