有什么策略可以“真正”禁用 systemd 服务吗?有些甚至在使用 systemctl 禁用后仍会启动

Ste*_*mit 10 systemd

似乎每当我尝试禁用 systemd 服务时,该服务都会找到某种方法来重新启用自身。最近的例子是 PackageKit,我发现它是我在这个问题中提出的问题的根源。如果我运行这个:

\n
systemctl disable packagekit\n
Run Code Online (Sandbox Code Playgroud)\n

然后几天后,我的磁盘保持稳定,但几天后,PackageKit 会重新启用自身并运行,并/var/cache/yum再次填充,将我的磁盘固定在 100%。

\n

我\xe2\x80\x99m 没有专门询问PackageKit;我真的\xe2\x80\x99m 试图了解systemd 服务停用应该如何工作。

\n

是否有任何通用的方法可以说 \xe2\x80\x9c 禁用此服务,并禁用任何自动重新启用它的方法?\xe2\x80\x9d 或者是我彻底删除我不\xe2 的包的唯一选择\x80\x99 不想运行吗?

\n
\n

更新:我的问题的一部分被误导了:systemctl disable确保服务无论如何都不会运行不是我们的工作;所做的只是systemctl disable说该服务不应在启动时自动运行。

\n

根据 user1686 的回答中的建议,我尝试过

\n
busctl --activatable | grep -i packagekit\n
Run Code Online (Sandbox Code Playgroud)\n

并得到了

\n
org.freedesktop.PackageKit      - -     -    (activatable) -       -\n
Run Code Online (Sandbox Code Playgroud)\n

所以这很可能表明是什么类型的事情正在启动它(如果不是在启动时)。busctl tree但在继续下一步之前我并没有想到要尝试。

\n

再次根据 user1686 的建议,我尝试了

\n
systemctl mask packagekit\n
Run Code Online (Sandbox Code Playgroud)\n

这似乎已经成功了 \xe2\x80\x94 无论之前启动了那个东西,都不再启动它了。\n我不知道这是否会被认为是丑陋的或暴力的或危险的解决方案;我不知道它是否会永远有效,但现在似乎有效。

\n

use*_*686 21

在 systemd 中“禁用”服务主要相当于在其他 init 系统中“从运行级别删除”(它从“multi-user.target”依赖树中删除该服务)。大多数情况下,这意味着该服务将不再在引导期间显式启动。

\n

但这并不意味着该服务不能以其他方式启动 \xe2\x80\x93 例如,您仍然可以手动systemctl start禁用服务,就像/etc/init.d/foo start过去一样。

\n

某些服务设置为以比简单的“启动时”更间接的方式启动,但仍然可以在系统仍在启动时触发其启动:

\n
    \n
  • 它们可能作为某些其他服务的显式依赖项而启动。如果其他服务碰巧在启动时启动,则该服务也会启动。

    \n

    尝试systemctl list-dependencies --reverse <unit>看看是否有任何东西想要或需要该服务。

    \n
  • \n
  • 它们可能有一个关联的.socket单元,一旦客户端尝试连接,该单元就会“按需”启动服务。(如果在启动期间尝试连接,那么该服务肯定看起来像是“启动时”启动的。)

    \n

    该服务systemctl status应该显示它是否由套接字或计时器单元\xe2\x80\x93 激活,这些单元也可以停止和禁用。

    \n
  • \n
  • 与按需套接字激活类似,服务可能由试图通过消息总线与服务通信的程序“D-Bus 激活”。(例如,packagekitd 可能会启动,因为 gnome 软件尝试在您登录时查询它。)

    \n

    通常,此类服务具有“systemctl禁用”删除的别名,以防止不必要的D-Bus激活已禁用的服务\xe2\x80\x93,但这并不总是正确实现。1

    \n
  • \n
\n

然而,除此之外,systemd 不会自动启用您已禁用的单元。如果您看到某个单元再次显式启用(例如,内部的符号链接multi-user.target.wants已重新创建),那么它一定是由外部事件触发的。

\n
    \n
  • 一些发行版使用 systemd预设来根据其总体策略重新启用或重新禁用单元,方法是在systemctl preset每次更新某些相关包时调用。(请参阅systemd.preset手册页。)如果您创建一个自定义预设来告诉 systemctl 始终禁用该服务,它将覆盖发行版的策略:

    \n
    (/etc/systemd/system-preset/00-steve.preset)\n\ndisable packagekit*.service\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
  • systemctl enable某些发行版在升级后脚本中直接调用硬编码。在这种情况下,屏蔽该单元将使 systemd 表现得好像它根本不存在 \xe2\x80\x93 它无法再启用、启动或以其他方式触摸:

    \n
    % systemctl disable --now packagekit\n% systemctl mask packagekit\n
    Run Code Online (Sandbox Code Playgroud)\n

    您的发行版的包管理器也可能有一个选项来完全跳过提取某些文件,这样就systemd 而言,它们实际上不再存在 \xe2\x80\x93 例如 pacman:

    \n
    (/etc/pacman.conf)\n\n[options]\nNoExtract = usr/lib/systemd/system/packagekit*\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
\n
\n

D-总线激活

\n

1如果您的服务在 中列出busctl --activatable,请尝试在其总线名称上使用eg busctl tree,看看这是否会使服务启动。

\n

如果与 org.freedesktop.PackageKit1 (或任何名称)交谈确实导致禁用的 systemd 服务启动,这通常意味着 D-Bus 文件.service指向错误的 systemd.service文件(是的,这些是不同的东西),或者它\根本不指向 systemd 服务(导致 dbus-daemon 直接生成该服务)。

\n

在前一种情况下,您可以屏蔽 systemd .service,并且 dbus-daemon 将不再能够启动它。在后一种情况下,您必须通过以下方式覆盖 D-Bus .service/usr/local/share/dbus-1或让您的包管理器根本不提取它(因为 dbus-daemon 没有相当于启用/禁用,也没有屏蔽/揭开面具)。

\n

  • 感谢您提供如此全面的概述。 (5认同)