我不想删除该服务,我只是想避免它在启动时启动。我仍然需要稍后手动启动它的选项(使用命令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
。顺便说一句,它想要的服务是一个例子正确的使用RefuseManualStart
和RefuseManualStop
:它应该仅在/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。生产系统升级缓慢,因此解决方案是再保留几年。