systemd:停止所有已卸载的单元

gfx*_*onk 3 systemd

我安装并运行了一些 systemd 单元。假设我手动foo.service卸载

  • 删除其 .service(和 .socket)文件
  • 删除所有符号链接(例如来自default.target.wants/)

我可以运行systemctl daemon-reload,然后我看到:

# systemctl status foo.service
foo.service
   Loaded: error (Reason: No such file or directory)
   Active: active (running) since Mon 2013-07-08 13:50:29 EST; 48s ago
 Main PID: 1642 (node)
Run Code Online (Sandbox Code Playgroud)

因此 systemd 知道它尚未安装,并且正在运行。是否有一些命令可以用来停止所有正在运行的不再有单元文件的服务?


我已经考虑过的事情:

  • systemctl isolate <current-target>

    这会产生副作用,即停止当前目标不需要的其他手动启动的服务。

  • 使用systemctl disable而不是手动删除文件

    我愿意,但这个脚本可能从可以访问正在运行的容器的文件系统的主机运行 - 它不能systemd直接调用。

  • 使用systemctl stop foo.service

    这意味着我知道哪些服务已被卸载。我不想弄清楚这一点(或记住它),我想要一个可以随时运行的通用命令来停止任何延迟的服务。

gfx*_*onk 5

我询问了邮件列表,Lennart Poettering 回复了以下建议:

http://lists.freedesktop.org/archives/systemd-devel/2013-July/012083.html

在此引用以供后人参考:


因此,处理此问题的正确方法是确保相关软件包包含正确的 scriplet,在卸载之前终止它们包含的所有单元。当然,我担心总会有像这样损坏的包,因此我完全可以看到你的用例。

目前没有很好的方法来处理这个问题,但你可以这样做:

$ systemctl --all --type=not-found --type=error
Run Code Online (Sandbox Code Playgroud)

这将列出加载状态为“错误”或“未找到”的所有单元(请注意,“未找到”仅在最近的版本中可用,而在较旧的 systemd 版本中只是“错误”的特殊情况'。上面的命令行适用于所有版本)。--type= 开关用于过滤单元类型,但实际上也可用于过滤负载状态。

然后过滤掉第一列:

$ systemctl --no-legend --all --type=not-found --type=error | awk '{ print $1 }'
Run Code Online (Sandbox Code Playgroud)

这将为您提供已引用或启动但尚未安装单元文件的单元文件列表。然后用它来停止单元:

$ systemctl stop `systemctl --no-legend -all --type=not-found --type=error | awk '{ print $1}'`
Run Code Online (Sandbox Code Playgroud)