当 dbus 信号启动时,如何触发多个 systemd 服务。
org.freedesktop.hostname1
我正在尝试通过创建如下服务来实现这一点:
[Unit]
Description=Set host name
[Service]
ExecStart=/home/administrator/set-hostname
BusName=org.freedesktop.hostname1
启用并运行后,netplan apply
脚本不会被执行。
助教。
答案1
我假设通过“触发”一项服务,您希望一项新服务开始运行(这是 systemd 可以做的事情),而不是让已经运行的服务做某事(这完全超出了 init 系统的范围)。
D-Bus 基础知识
每个 D-Bus 消息都有一个“收件人”字段(可以是众所周知的名称,例如org.example
,也可以是唯一的名称,例如:1.234
,或者是广播地址)。
D-总线信号(发送以发布已经发生的事件)通常会广播到整个总线,因此它们不会导致任何服务启动。如果您正在考虑发送到具体的服务,那些通常是方法调用,而不是信号。
D-Bus 服务自动启动
总线守护进程将在以下情况下自动启动服务:
- 有一条消息发送给某个知名人士,
- 并且这项众所周知的服务目前还没有在公交车上被“认领”,
- 并且该知名名称在 下有一个对应的 D-Bus .service 文件(不要与 systemd .service 文件混淆)
/usr/share/dbus-1/system-services/
。
从第 2 点开始,需要注意的是,只有一个服务可以声明一个众所周知的名称并接收发往该名称的消息。只要真正的 systemd-hostnamed 已在运行并声明org.freedesktop.hostname1
,它就会接收这些消息 - 其他进程无法执行相同操作。
同样的点 #2 也意味着自动启动不会发生查找服务当前持有的名称。消息将直接传送给已在运行的服务。
在第 3 点中,文件的名称必须确切地与知名的总线名称匹配;即您不能让多个服务以相同的名称竞争自动启动。因此,就 dbus-daemon 而言,每条消息最多只能启动一个服务。
通过 systemd 自动启动
如果 D-Bus .service 文件(在 /usr/share/dbus-1/…/ 下)包含一个SystemdService=
选项,dbus-daemon 将尝试通过 systemd 启动该服务,而不是传统地分叉/执行 Exec= 中列出的任何内容。
(通常 systemd 服务会安装一个名为– 的别名,这只是允许 systemctl 启用/禁用的一种约定,除此之外,该语法没有特殊含义。)dbus-[busname].service
由于 systemd 服务可以依赖项,现在您有一个解决“每条消息只能启动一个服务”限制的解决方法:直接激活的服务可以拉入其他服务作为依赖项。但是,之前解释的所有内容仍然适用 - 一旦“真实”服务正在运行,其他消息将直接到达它,并且不会触发自动启动。
结论
看起来您正在尝试完全避免使用 systemd-hostnamed,并且每当 netplan 调用 hostnamed 的SetHostname()
方法时,您都希望自己的程序能够接收它。
简单的 shell 脚本无法做到这一点。您无法通过 stdin、环境变量或命令行参数接收 D-Bus 消息。您的脚本只会知道它是为一些原因,但它不知道它到底应该做什么。
但它是一般情况下是可行的——只要您使用的编程语言具有 D-Bus 模块。您“仅”需要连接到系统总线、声明名称、接收消息,并以与 systemd-hostnamed 相同的方式处理它们。许多 dbus 模块都附带“骨架 D-Bus 服务”示例。
(事实上,已经有各种 systemd 守护进程的第三方重新实现,例如 LoginKit、systembsd、systemd-shim。)