如何要求 systemd 在启动时不启动系统服务?

如何要求 systemd 在启动时不启动系统服务?

我不想删除该服务,我只是想避免它在启动时启动。我仍然需要稍后手动启动它的选项(使用命令systemctl start <service>)。

我尝试使用systemctl disable <service>.它不起作用,因为它删除了该服务。

还有另一种可能。在其服务文件中,

[Install]
#WantedBy=multi-user.target

可以被注释掉(然后,systemctl daemon-reload)。它适用于我自己的服务,因为他们的服务文件是我编写的。

但是,属于分发版的服务文件位于/lib/systemd/system.该目录中的文件由操作系统管理,即它们将被更新覆盖,系统的其他部分可能假设这些文件未被修改,等等。简单地编辑系统文件是/etc一种不好的做法,我不想这样做。我不想编辑我的/lib.

该怎么办?

答案1

systemctl disable是执行此操作的正确方法;它仍然允许手动启动一个单元,即使它没有出现在systemctl --all的输出中 - 要列出所有可启动的单元,您应该运行systemctl list-unit-files。要使一个单元无法启动,您需要mask它。

$ sudo systemctl stop unbound
$ sudo systemctl status unbound
● unbound.service - Unbound DNS server
   Loaded: loaded (/lib/systemd/system/unbound.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Fri 2019-05-03 13:12:41 CEST; 5s ago
     Docs: man:unbound(8)
 Main PID: 5320 (code=exited, status=0/SUCCESS)

$ sudo systemctl disable unbound
$ sudo systemctl status unbound
● unbound.service - Unbound DNS server
   Loaded: loaded (/lib/systemd/system/unbound.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:unbound(8)

$ sudo systemctl start unbound
$ sudo systemctl status unbound
● unbound.service - Unbound DNS server
   Loaded: loaded (/lib/systemd/system/unbound.service; disabled; vendor preset: enabled)
   Active: active (running) since Fri 2019-05-03 13:13:14 CEST; 1s ago
     Docs: man:unbound(8)
  Process: 30513 ExecStartPre=/usr/lib/unbound/package-helper chroot_setup (code=exited, status=0/SUCCESS)
  Process: 30518 ExecStartPre=/usr/lib/unbound/package-helper root_trust_anchor_update (code=exited, status=0/SUCCESS)
 Main PID: 30525 (unbound)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/unbound.service
           └─30525 /usr/sbin/unbound -d

如果您确实愿意,可以/lib通过在 中添加文件来覆盖 中定义的系统提供的服务/etc,并更改其所需的目标;systemctl edit yourunit会做正确的事情:它会打开一个编辑器,允许您仅覆盖您关心的设置,并且它将结果存储在正确的位置,作为覆盖“片段”。对系统提供的服务中的非覆盖设置进行了更新(例如通过软件包升级)将被透明地考虑在内。

答案2

我没想到会写出这么长的答案,但您似乎一直在使用 systemd 尝试不同的事情,并且我认为您对它的机制更感兴趣,而不仅仅是简单地输入一次魔术命令并忘记它的存在。我可以谈论 systemd 很多很多!

我。

从管理的角度来看,斯蒂芬·基特的回答非常好,也很详尽(我很高兴投赞成票),当你作为管理员想要禁止某项服务启动或启用。正如 systemd 文档 v241 所说(请参阅 参考资料man 5 systemd.unit):

如果单元文件为空(即文件大小为 0)或符号链接到/dev/null,则不会加载其配置,并且加载状态为“屏蔽”,并且无法激活。使用此方法可以有效地完全禁用某个单元,甚至无法手动启动它。

systemctl mask正是这样做的:它创建一个与下面的单元同名的符号链接/etc,并将服务文件符号链接到/dev/null.由于 systemd 首先查找/etc(该顺序在同一手册中的第一行中给出)并找到指定的单元,因此它发现该单元被屏蔽。它是为此而设计的,如果您想阻止某项服务被启用和启动,请使用它。这是最简单的单命令解决方案,重启后仍然有效。能简单做的事情就保持简单。

二.

但是,如果您是设计一组相互依赖的服务,其角色是系统建造者而不是管理员,使用命令声明服务不可启动或不可停止是有意义的systemctl,同时仍然允许其他机制(套接字、dbus 等)按需启动它。为此,systemd 有设置,也在同一手册中进行了描述:RefuseManualStart=RefuseManualStop=

采用布尔参数。如果为 true,则该单元只能间接激活或停用。在这种情况下,用户请求的显式启动或终止将被拒绝,但是,如果它作为另一个单元的依赖项而启动或停止,则启动或终止将成功。这主要是一种安全功能,以确保用户不会意外地激活不打算显式激活的单元,也不会意外地停用不打算停用的单元。这些选项默认为 false。

您可以启用此类服务​​,但它将拒绝启动systemctl start(或停止,对于其他设置),以防止操作员错误。

三.

[Install]根据您在服务文件中注释该部分的想法建议,需要详细说明一点:

[Install]
#WantedBy=multi-user.target

如果系统自带服务,请勿这样做,也就是说,当单元文件位于/lib层次结构下的某个位置时!升级要么默默地覆盖它,要么要求您手动干预以合并更改。 systemd 对此有更好的机制。按照惯例(对于系统服务),systemd 下的目录/etc是“yours”,但下一个目录/lib属于发行版。

例如,如果您想WantedBy=从该[Install]部分中删除该子句,则应该使用 systemd 适当的机制对服务进行一些调整:使用命令sudo systemctl edit servicename.service。 systemd 将为您打开一个编辑器,最初该文件将为空。

systemd 的下一个有用的属性是,当关键字值是一个列表(例如WantedBy)时,为其分配一个空字符串会重置列表(不同版本中存在不一致的情况,但大多数情况下它是有效的。在我们的例子中确实如此)。在编辑器中,添加两行(这只是您尝试过的概念的详细阐述,但尚未完全达到可行的解决方案;我们已经知道您将通过屏蔽实现您想要的目标):

[Install]
WantedBy=

这会将WantedBy列表重置为空。如果您想添加另一个依赖项,只需添加具有相同键的另一行(WantedBy=another.service在我们考虑不周的示例中是另一个 )。幕后实际发生的事情,systemd 创建了一个覆盖文件位于/etc, i. e.在你的、机器所有者的目录,并承诺永远不会碰它。假定默认目录布局为 .systemd 创建的文件被命名为/etc/systemd/system/servicename.service.d/override.conf.这里是部分服务名.service正是您要覆盖的单位名称。 systemd 尊重这个新子目录中与模式匹配的所有文件*.conf,因此可以不仅仅是override.conf;只需注意它们将按名称的字典顺序应用,最低的在前(如ls -1 *.conf | LC_ALL=C sort所示)。

虽然在您的情况下这不是一个正确的机制,正如彼得已经在后续评论中回答的那样,但有时当您想要添加环境变量,甚至是添加环境变量时,它会很有帮助。解决错误1、像

$ cat /etc/systemd/system/systemd-remount-fs.service.d/override.conf
# Workaround for the systemd bug #14603: remount-fs and growfs@
# race, so that the latter may fail because the root fs is still
# readonly. This dependency ensures that the remount happens first.
[Unit]
[email protected]

您可以使用以下命令验证您的覆盖是否已合并到设备配置中systemctl show myunit.service。它的输出非常详细,所以使用 grep:

$ systemctl show systemd-remount-fs.service | grep ^Before=
Before=systemd-update-utmp.service [...] [email protected] [...]

这不是世界上最清晰的示例,因为该行很长;我在标记处删除了大部分内容,但您可以在列表中[...]找到。[email protected]即使在尝试不同的启动/停止/启动/休眠和其他场景之前,最好始终验证配置更改是否确实已纳入设备的组合设置中。拼写错误时有发生。

四.

当然,您可以调整任何类型的单元,不仅是服务:计时器、套接字、安装等。甚至单元文件动态生成的在目录下/run尊重这些调整。例如,尽管在以下情况下/opt使用常规挂载,但 systemd 会在 RAM 文件系统目录中为其/etc/fstab生成一个临时单元。这个临时单位完美地识别了opt.mount/run/systemd/system额外Wants=指定/etc/systemd/system。顺便说一句,它想要的服务是一个例子正确的使用RefuseManualStartRefuseManualStop:它应该仅在/opt文件系统安装和卸载时完成其工作,如果手动启动,则会挂起或吐出错误。更糟糕的是,它不会/opt如果文件系统已被手动启动,则在安装文件系统后立即启动!

BindsTo=opt.mount该服务还通过指定和 来显示“强绑定”模式After=opt.mount。引用 systemd.unit(5) 手册,在“[UNIT] SECTION OPTIONS/BindsTo=”下,将我的添加放在括号中以使语言更容易理解:

当在同一单元[,]上与 After= 结合使用时,BindsTo= 的行为甚至更强。在这种情况下,[该单元所]绑定的单元[必须]处于活动状态,该单元也[并保持]处于活动状态。

这里的含义是,该单元在停止之后启动,在opt.mount停止之前停止,以严格的步调。

** **

systemd 是一个庞大、强大且灵活的系统,如果您正在以尽可能最佳的方式调整系统,那么man当您对其他事情感到厌倦时,阅读 Web 上的文档肯定是有益的。


1 该错误已于一年多前得到修复,并且该修复已进入 systemd 245 版本,但由于我正在聚集一系列不同的发行版,并且有时会从较旧的映像中汇总虚拟机,因此我必须保留它有一段时间了。 Debian 10 有 systemd 的前缀 v241;仅 Debian 11 附带 v247。生产系统升级缓慢,因此解决方案是再保留几年。

相关内容