"systemctl mask"和"systemctl disable"之间有什么区别?

我想通过在启动时禁用plymouth服务来提高我的Ubuntu GNOME 16.04的启动时间。我在各种网站上找到了两个关于如何做到这一点的答案。
# systemctl disable plymouth-quit-wait.service 
# systemctl mask plymouth-quit-wait.service 

我不知道它们的作用,所以无法执行上述任何一项任务。

6请在这里阅读 https://fedoramagazine.org/systemd-masking-units/ - Rinzwind
我不会说你在不知道这些命令的作用之前就不能运行它们。但你明智地选择不这样做。 - flarn2006
3个回答

如果一个服务是“启用”的,那么就会在某个地方有一个符号链接。
/etc/systemd/system

通常情况下,将其存放在一个单元文件中
/lib/systemd/system

帮助地,在你启用一个服务时,创建的链接和目标的完整路径将会被打印到stdout。
禁用服务会删除符号链接,所以单位文件本身不受影响,但在下一次系统引导时不会加载该服务,因为systemd会读取/etc/systemd/system目录。
然而,禁用的服务可以被加载,并且将会在启动依赖于它的服务时自动启动;enable和disable只配置了单位的自动启动行为,其状态可以轻松覆盖。
一个被屏蔽(masked)的服务是指其单位文件是对/dev/null的符号链接。这使得即使其他已启用的服务需要该服务,也"无法"加载它。
当你屏蔽一个服务时,会在/etc/systemd/system和/dev/null之间创建一个符号链接,原始单位文件保持不变。当你取消屏蔽一个服务时,符号链接将被删除。

然而,我注意到这些指令并不总是被遵守。

当我试图屏蔽大多数服务时,它会失败:

$ sudo systemctl mask bluetooth.service
Failed to execute operation: Invalid argument

当然,我首先停止了服务。@Anwar建议只有非关键服务才能进行掩码。
除非我自己掩码了它,否则解除掩码的服务也会失败(无声)。我相信这是因为除了在/lib/systemd/system中以符号链接的形式指向/dev/null之外,该服务没有任何单元文件存在:
$ file $(locate fuse.service)
/lib/systemd/system/fuse.service: symbolic link to /dev/null
$ sudo systemctl unmask fuse.service
$ systemctl status fuse
● fuse.service
   Loaded: masked (/dev/null; bad)
   Active: inactive (dead)

我不是唯一一个遇到这个问题的人

为了真正揭示被掩盖的服务x11-common,我不得不删除指向/dev/null的符号链接,并执行sudo apt-get install --reinstall x11-common && sudo systemctl daemon-reload。现在当我使用systemctl status x11-common查询时,我看到该服务有一个漂亮的绿色圆圈,已加载并处于活动状态(已退出),尽管它没有单元文件。

如需进一步参考,可以查看如何使用Systemctl这篇文章。


1嗯,我得到了systemctl status x11-common ● x11-common.service Loaded: masked (/dev/null; bad) Active: inactive (dead)。这是不好的吗?但我用的是Debian,不是Ubuntu。无论如何,解释得很好。谢谢。 - Faheem Mitha
@FaheemMitha 我不确定是否需要这项服务 - 我的系统似乎可以在没有它的情况下正常工作。不过,对于Debian我没有任何经验,抱歉! - Zanna

这很简单。

  • systemctl start, systemctl stop:立即启动(停止)相关的单元;
  • systemctl enable, systemctl disable:将单元标记为在系统启动时自动启动(或取消标记),具体方式在其[Install]部分描述;
  • systemctl mask, systemctl unmask:禁止(允许)任何尝试手动启动该单元,或作为任何其他单元的依赖项,包括默认引导目标的依赖项。请注意,systemd中的自动启动是通过将默认引导目标与相关单元添加一个人工依赖关系来实现的,因此“屏蔽”也会禁止自动启动。

参考:systemctl(1)

更多信息:Lennart Poettering (2011-03-02)。"离开的三个层面"管理员使用的systemd。0pointer.de。

简而言之,
  • disable 在启动时禁用单元。但该单元可以在启动后的任何时间启动。

  • mask 完全禁用单元。除非解除屏蔽,否则无法启动。这自动意味着它在启动时将失败。


1我很好奇 - maskunmask 对你有效吗?(如果你不想测试,我完全理解!) - Zanna
1@Zanna 是的。这确实有效。我之前进行过测试,刚刚再次测试了一下,使用 postgresql@9.5-main.service 服务。 - Anwar
嗯,我得弄清楚为什么它对我不起作用。我知道我不是唯一一个遇到这个问题的人。 - Zanna
1可能适用于非关键服务。我觉得这还是很新的。顺便说一句,你的回答更加详细和有帮助。 - Anwar
@安瓦尔 关于“它在启动过程中会失败”的问题。确实,它无法加载并且处于非活动状态(已停止),但是一个被屏蔽的服务不会阻塞依赖于它的其他服务。如果它真的失败了,那么它将会阻塞这些服务。 - Andrew Straw