我不想删除该服务,我只想避免它在启动时启动。我仍然需要稍后手动启动它的选项(使用systemctl start <service>
命令)。
我尝试使用systemctl disable <service>
. 它不起作用,因为它删除了服务。
还有另一种可能。在其服务文件中,
[Install]
#WantedBy=multi-user.target
可以被注释掉(然后,systemctl daemon-reload
)。它适用于我自己的服务,因为他们的服务文件是由我编写的。
但是,属于分发的服务文件位于/lib/systemd/system
. 此目录中的文件由操作系统管理,即它们将被更新覆盖,系统的其他部分可能会假定这些文件未修改,等等。简单地编辑系统文件/etc
是一种不好的做法,我不想这样做。我不想在我的/lib
.
该怎么办?
systemctl disable
是这样做的正确方法;它仍然允许手动启动一个单元,即使它没有出现在systemctl --all
的输出中——要列出所有可启动的单元,你应该运行它systemctl list-unit-files
。要使单元无法启动,您需要mask
它。如果你真的想要,你可以通过在 中
/lib
添加文件来覆盖定义的系统提供的服务/etc
,并更改它们所需的目标;systemctl edit yourunit
会做正确的事:它会打开一个编辑器,允许您仅覆盖您关心的设置,并将结果存储在正确的位置,作为覆盖“片段”。对系统提供的服务中的非覆盖设置的更新(例如通过包升级)将被透明地考虑在内。我没想到会写这么长的答案,但是您似乎一直在尝试使用 systemd 做不同的事情,而且我假设您对它的机制更感兴趣,而不是仅仅输入一次魔术命令并忘记它的存在。而且我可以谈论 systemd 更多、更长的时间!
我。
当您作为管理员想要禁用服务启动或启用时,Stephen Kitt 的回答从管理的角度来看非常好且详尽(我很乐意对其进行投票) 。正如 systemd 文档 v241 所说(参见 参考资料
man 5 systemd.unit
):systemctl mask
正是这样做的:它创建一个与下面的单元同名的/etc
符号链接,并将服务文件符号链接到/dev/null
. 由于 systemd/etc
首先查找(顺序在同一手册中的第一行给出),并找到命名的单元,它发现该单元被屏蔽了。它就是为此而设计的,如果您想阻止服务被启用和启动,请使用它。这是最简单的单命令解决方案,可以在重新启动后继续存在。保持简单可以做的事情简单。二、
但是,如果您正在设计一组相互依赖的服务,以系统构建者而不是管理员的角色,使用
systemctl
命令声明服务不可启动或不可停止,同时仍然允许其他机制(套接字,dbus等)按需启动它。为此,systemd 具有设置,也在同一手册中进行了描述:RefuseManualStart=
和RefuseManualStop=
:您可以启用这样的服务,但它会拒绝启动
systemctl start
(或停止,对于其他设置),以防止操作员错误。三、
[Install]
根据您在服务文件中评论该部分的想法提出的要详细说明的一点:如果系统自带服务,即当单元文件位于层次结构下的某个位置时,请不要这样做
/lib
!升级将静默覆盖它,或要求您手动干预以合并更改。systemd 对此有更好的机制。按照惯例(对于系统服务),systemd 的目录/etc
是“你的”,但下面的目录/lib
属于发行版。例如,如果您想
WantedBy=
从该部分中删除该子句[Install]
,则应使用 systemd 适当的机制对服务进行少量调整:使用 commandsudo systemctl edit servicename.service
。systemd 将为您打开一个编辑器,最初该文件将为空。systemd 的下一个有用的属性是,当关键字值是一个列表(例如
WantedBy
)时,为其分配一个空字符串会重置列表(不同版本存在不一致,但大多数情况下它都有效。在我们的例子中它确实)。在编辑器中,您添加两行(这只是对您尝试但尚未完全达到工作解决方案的概念的详细说明;我们已经知道您将通过屏蔽来实现您想要的):这会将
WantedBy
列表重置为空。如果您想添加另一个依赖项,只需将另一行与相同的键(另一个WantedBy=another.service
,在我们考虑不周的示例中)。在幕后实际发生的情况是,systemd在i下创建了一个覆盖文件。/etc
e. 在您的机器所有者的目录中,并承诺永远不会碰它。假设默认目录布局,systemd 创建的文件名为/etc/systemd/system/servicename.service.d/override.conf
. 这里的部分servicename.service正是您要覆盖的单元名称。systemd 尊重这个新子目录中的所有文件,因此可以不只是override.conf
; 只需要注意它们将按名称的字典顺序应用,最低的在前(如ls -1 *.conf | LC_ALL=C sort
将显示的那样)。虽然在您的情况下不是正确的机制,正如彼得已经在后续评论中回答的那样,但有时在您想要添加环境变量或什至解决错误时它会有所帮助¹,例如
systemctl show
您可以使用myunit.service验证您的覆盖是否已合并到单元配置中。它的输出非常冗长,所以使用 grep:这不是世界上最清晰的例子,因为这条线很长;
[...]
我在标记所在的位置删除了大部分内容,但您可以[email protected]
在列表中找到。即使在尝试不同的启动/停止/启动/休眠和其他方案之前,始终验证配置更改是否确实将其纳入单元的组合设置是一个很好的做法。发生拼写错误。四。
自然地,您可以调整任何类型的单元,不仅是服务:计时器、套接字、挂载等。甚至在目录下动态生成
/run
的单元文件也尊重这些调整。例如,尽管在以下情况下,/opt
挂载是使用常规挂载的,但 systemd会在内存文件系统目录中为其/etc/fstab
生成一个临时单元。这个临时单元完全识别. 而且,顺便说一下,它想要的服务是正确使用and的一个例子:它应该只在文件系统挂载和卸载时完成它的工作,如果手动启动它会挂起或吐出错误。更糟糕的是,它opt.mount
/run/systemd/system
Wants=
/etc/systemd/system
RefuseManualStart
RefuseManualStop
/opt
/opt
如果文件系统已经被手动启动,它就不会在文件系统安装后启动!BindsTo=opt.mount
该服务还通过同时指定和来显示“强绑定”模式After=opt.mount
。引用 systemd.unit(5) 手册,在“[UNIT] SECTION OPTIONS/BindsTo=" 下,在括号中添加我的内容以使语言更易于理解:这里的含义是,该单元在停止之后启动并在停止之前
opt.mount
停止,以紧密的步调一致。* * *
systemd 是一个大型、强大且灵活的系统,如果您在以最佳方式调整系统之后,
man
当您对其他事情感到厌烦时,在 Web 上或 Web 上阅读它的文档肯定是有益的。¹ 一年多以前,该错误已被修复,并且该修复已进入 systemd 的 245 版,但由于我正在部署一系列不同的发行版,有时还会从旧映像中汇总 VM,因此我必须保持一会儿。Debian 10 有一个 systemd 的前缀 v241;只有 Debian 11 带有 v247。生产系统升级缓慢,因此解决方法是多停留几年。