反例解释

反例解释

我读过了什么是多用户目标系统文档,它指出 multi-user.target 是一个特殊目标。此外,很多系统示例包含该行。

  1. 为什么这么多示例服务都包含该行?
  2. 如果它们不包含 WantedBy=multi-user.target 会发生什么?
  3. 您能否举个例子,说明何时实际上建议在服务文件定义中不包含该行?
  4. 同样,什么时候保留这条线是个好主意?

答案1

1.)multi-user.target基本上是经典 SysVinit 运行级别 3 最接近的等效版本systemd。当systemd系统启动时,systemd正在尝试使系统状态与 - 指定的状态匹配,这通常是或 的default.target别名。graphical.targetmulti-user.target

multi-user.target通常定义一个系统状态,其中所有网络服务都启动并且系统将接受登录,但本地 GUI 未启动。这是服务器系统的典型默认系统状态,这些系统可能是远程服务器机房中的机架式无头系统。

graphical.target是 的另一个可能的别名default.target。通常它被定义为 的超集multi-user.target:它包括multi-user.target所做的一切,加上本地 GUI 登录的激活。有点像经典 SysVinit 中的运行级别 5。

服务中的这一行WantedBy=multi-user.target本质上与在 SysVinit 系统中指定“此服务应在运行级别 3、4 和 5 中启动”相同:它告诉systemd该服务应作为正常系统启动的一部分启动,无论是否是本地服务GUI 处于活动状态。

然而,它WantedBy与启用/禁用状态是分开的:所以从另一种意义上来说,它是一种“预设”:它确定在什么条件下可能会发生自动启动,但仅当服务首先启用时。

2.) 如果您省略该WantedBy=multi-user.target行并且没有其他启用的服务在其服务定义中包含Requires=your.serviceWants=your.service,则您的服务将不会自动启动。

systemd适用于依赖项,并且在启动时,如果您的服务没有任何内容RequiresWants即使启用了该服务,它也不会启动。

当然,您可以编辑您想要在启动时启动的任何服务的default.target添加或删除RequiresWants行 - 但这样您就可以将一个新的服务文件放入系统中并使其默认工作(这使得软件变得非常容易)包管理器),systemd具有WantedByRequiredBy关键字,可用于(分别)从“另一端”插入Wants和键入依赖项。Requires

3.) 如果你希望该服务在启动时自动启动,或者该服务是您明确定义的依赖关系链的一部分。

例如,您可能正在重构服务器应用程序 A,并出于某种原因决定将某些可选功能从其中分离到单独的服务 B 中,以允许用户选择在不需要时不安装它。然后,您可以将服务 B 设为单独的service-B.rpm,并定义 ,B.service以便在服务 A 启动时自动启动服务 B - 但仅在实际安装时才WantedBy=A.service启动。systemdservice-B.rpm

请注意,WantsWantedBy仅表示系统应在启动另一个服务或目标时启动一个服务,但它根本没有指定有关启动/关闭顺序的任何内容。如果您需要在服务 A 启动时服务 B 已经运行,则需要Before=A.service在该B.service文件中添加以显式指定启动顺序依赖项。

4.) 任何时候你希望服务能够在启动时自动启动,并且没有定义其他依赖项。

答案2

如果您删除WantedBy=multi-user.target,那么systemctl enable your-example-here将(吵闹地)无法执行任何操作。

图形目标

如果您从源安装纯 systemd,则它引导到的“默认目标”是graphical.target.

启动graphical.targetstarts multi-user.target,加上提供图形用户界面所需的任何单元。这种额外的复杂性是为了模拟遗留的“运行级别”而安排的。

真的应该忽略/掩盖“运行级别”模拟;无论如何它都不能正常工作。对不起!我想历史上强调“图形”与“多用户”的原因是图形软件 1)不如系统的其他部分强大和成熟,2)需要大量资源。

通常只有少数单位特定于graphical.target. GUI 本身有一个服务,例如gdm.target.有一些支持服务大多这里的 GUI 也使用它。

编辑:谷歌搜索建议,如果您没有安装 GUI,但“默认目标”已保留为graphical.target,则 systemd 可能会记录警告。 “无法为单位 display-manager.service 添加依赖项作业,忽略:单位 display-manager.service 加载失败:没有此类文件或目录。”我们希望避免日志中出现不必要的警告。因此,如果您没有安装 GUI,那么使用systemctl set-default multi-user.尽管您的操作系统的安装系统可能已经为您解决了这个问题。除此之外,我强烈支持对此事保持冷漠:-)。

系统初始化目标

某些服务和其他类型的单元“参与早期启动”。它们被定义为Before=sysinit.target直接或间接启动。大多数服务仅启动After=sysinit.target- 这是自动的情况,除非服务设置DefaultDependencies=no.

多用户目标

大多数示例服务不属于上述任一类别,因此我们将它们附加到multi-user.target。这包括大多数网络服务(例如网络服务器),它们是原型系统服务。

动态激活的服务

您可能会看到的另一种可能性是服务单元不是启动时自动启动。所以就不需要了WantedBy=multi-user.target。该服务可以由其他东西触发或“激活”。

其中一个例子是 dbus 激活的服务。可以将 Dbus 配置为在对服务进行 dbus 调用时按需启动服务。

对于网络服务,您可以使用套接字激活的服务。这可能更容易找到详细信息,因为所有配置都在 systemd 单元中。例如sshd.socketorssh.socket通常可用于激活[email protected]or [email protected]。尽管如此,我认为在启动时启动 sshd 服务更为常见。


与往常一样,上述内容进行了简化并省略了似乎不需要的细节。

答案3

multi-user.target是一个语义名称,也就是说,它与一个含义相关联。请允许我用一个反例来演示这个概念。我将论证使用的决定multi-user.target取决于上下文。

如果你要创建一个 systemd用户单位配置而不是系统单位配置中,您可能会天真地遵循 systemd 系统单位的约定并使用multi-user.target1

反例解释

考虑文件/home/jonathan/.config/systemd/user/coolstuff.service

该用户只能用于 user jonathan,因此将我的目标称为“multi-user.target”几乎没有意义。

[Unit]
Description=Does some cool stuff.

[Service]
ExecStart=/bin/bash -c '/usr/bin/echo "Cool stuff" >> %h/coolstuff.txt'

[Install]
WantedBy=user.target

请注意我如何选择使用WantedBy=用户.目标。这是因为此上下文的范围是我的用户帐户,因此我选择使用我自己的语义约定。换句话说,多个用户不会受到本机的影响。然而,在系统级别,由于并行启动顺序,遵循标准化约定更有意义。在启动过程中,许多过程集中在多个目标上。它multi-user.target在语义上与“读取用户参与/与系统交互”的想法相关联(没有 telcoM 提到的窗口系统),因此对于大多数系统单元文件来说它是一个安全的选择。

脚注

  1. 尽管在这种情况下它没有意义,但它仍然有效。

相关内容