是否有任何策略可以真正禁用 systemd 服务?有些服务即使在使用 systemctl 禁用后仍会启动

是否有任何策略可以真正禁用 systemd 服务?有些服务即使在使用 systemctl 禁用后仍会启动

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

systemctl disable packagekit

然后几天内我的磁盘保持稳定,但几天后,PackageKit 重新启动,运行并/var/cache/yum再次填满,使我的磁盘占用率达到 100%。

我并不是专门询问 PackageKit;实际上,我想了解 systemd 服务停用应该如何工作。

是否有任何通用方法可以说“禁用此服务,并禁用任何自动重新启用它的方式?”或者我唯一的选择是彻底删除我不想运行的程序包?


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

根据用户 1686 的回答中的建议,我尝试过

busctl --activatable | grep -i packagekit

并得到

org.freedesktop.PackageKit      - -     -    (activatable) -       -

因此这很可能表明是什么原因导致了这个问题(如果不是在启动时)。但busctl tree在继续下一步之前,我并没有想过要尝试一下。

再次按照 user1686 的建议,我尝试了

systemctl mask packagekit

而这似乎起了作用——之前启动那个东西的任何东西都不再启动它了。我不知道这是否会被认为是一种丑陋、暴力或危险的解决方案;我不知道它是否会永远有效,但目前看来它是有效的。

答案1

在 systemd 中“禁用”服务基本上等同于在其他 init 系统中“从运行级别中删除”(它会从“multi-user.target”依赖关系树中删除服务)。大多数情况下,这意味着该服务将不再明确地在启动过程中启动。

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

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

  • 它们可能作为其他服务的显式依赖项启动。如果其他服务恰好在启动时启动,则此服务也会启动。

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

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

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

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

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

然而除此之外,systemd 不会自动使能够您已禁用的单元。如果您看到某个单元再次被明确启用(例如,其中的符号链接multi-user.target.wants已重新创建),那么它一定是由外部因素触发的。

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

    (/etc/systemd/system-preset/00-steve.preset)
    
    disable packagekit*.service
    
  • systemctl enable一些发行版在升级后脚本中直接调用硬编码。在这种情况下,掩蔽该单元将使 systemd 表现得好像它根本不存在——它不再能被启用、启动或以其他方式触及:

    % systemctl disable --now packagekit
    % systemctl mask packagekit
    

    你的发行版的包管理器可能还有一个选项可以跳过完全提取某些文件,这样它们就可以字面上地对于 systemd 来说不再存在 – 例如 pacman:

    (/etc/pacman.conf)
    
    [options]
    NoExtract = usr/lib/systemd/system/packagekit*
    

D-Bus 激活

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

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

在前一种情况下,您可以屏蔽 systemd .service,这样 dbus-daemon 将无法再启动它。在后一种情况下,您必须通过覆盖 D-Bus .service/usr/local/share/dbus-1或让您的包管理器根本不提取它(因为 dbus-daemon 没有等效的启用/禁用或屏蔽/取消屏蔽功能)。

相关内容