如何让systemd守护进程运行DBus服务

问题描述 投票:0回答:1

我使用 python 创建了 PyQt5 程序和守护进程。它们应该通过 dbus 进行通信 - 程序发送

dbus-send --session --dest="org.example.dirswatcher" --type="method_call" --print-reply "/" "org.example.dirswatcher.update_dirs_to_watch"
并相应地执行守护进程中的
update_dirs_to_watch
方法。当我测试时,一切正常,但是当我从 dirswatcherd.py 文件创建守护程序并尝试执行我的 PyQt5 应用程序时,它显示 Error org.freedesktop.DBus.Error.ServiceUnknown:名称 org.example。任何 .service 文件都没有提供 dirswatcher。 是的,我做了所有
systemctl
的事情,并且守护进程处于“激活”状态(有时当我更改 .service 或 .conf 文件时,状态为绿色,但仍然没有提供 DBus 服务)

我也做的是:

  1. 将 .conf 文件放入
    /etc/dbus-1/system.d/org.example.dirswatcher.conf
    ,
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <policy context="default">
    <allow own="org.example.dirswatcher"/>
    <allow send_destination="org.example.dirswatcher"/>
    <allow receive_sender="org.example.dirswatcher"/>
  </policy>
</busconfig>
  1. 将 .service 文件放入
    /etc/systemd/system/dirswatcher.service
[Unit]
Description=Dirs watcher
After=network.target

[Service]
User=omen
ExecStart=/usr/bin/python3 /home/user/file-manager/daemon/dirswatcherd.py
Restart=always

[Install]
WantedBy=multi-user.target

还有。

dirswatcherd.py

class Service(QDBusAbstractAdaptor, QObject):
    Q_CLASSINFO('D-Bus Interface', 'org.exmaple.dirswatcher')

    def __init__(self, parent):
        super().__init__(parent)
        QDBusConnection.sessionBus().registerObject("/", parent)

        if not QDBusConnection.sessionBus().registerService("org.exmaple.dirswatcher"):
            print(QDBusConnection.sessionBus().lastError().message())
...
python linux systemd dbus
1个回答
0
投票

您的错误消息有点引导您走向错误的方向。它意味着两件事 – 它表示 1) 当前没有运行具有此类名称的服务 并且 2) D-Bus 尝试“按需”启动它,但不知道如何启动。

虽然第二部分很容易修复(通过创建第二种不同类型的 .service 文件),但在您的情况下,这实际上与您正在解决的问题无关 - 它不是 D-Bus 的强制部分;这只是一种“按需启动”机制,但这不是您正在做的。你的 systemd 配置甚至服务名称都暗示你希望它永久运行,所以你实际上不需要让 D-Bus 再次启动它。(除此之外,名称“dirswatcherd”类型of 意味着它应该是一个永久运行的服务,因此按需激活无论如何都不适合它。)

您应该关注第一部分:当前没有这样的服务正在运行,即使您尝试通过 systemd 启动它。您说您只看到状态“激活”,这意味着您的服务

不断崩溃。如果您看到服务“正在激活”但它从未变为“活动”,那么您应该做的第一件事就是检查 systemd 日志通过 journalctl -b -u dirswatcher

 看看发生了什么。

最有可能发生的情况是,您的程序正在尝试连接到会话总线,但您将其作为系统服务运行(并且出于某种原因,为

system 总线添加 .conf 文件,即使这不是同样的事情)。

关键点是

系统服务无法访问会话总线。即使你设置了“User=omen”也不能。 (是的,他们可以被“制作”为有权访问某个特定用户的会话总线,但重点是您“不应该”这样做,即使有可能。)同样,他们无权访问你的 GUI – 这也是“会话”的一部分。 (这可能就是您只看到“正在激活”而从未看到“活动”的原因 - 服务始终无法启动,因为它没有总线访问权限,而您的“重新启动=始终”只是掩盖了问题。)

一般来说,用户级服务(例如,在调用者的用户帐户下运行的东西,尤其是与 X11/Wayland GUI 交互的东西)应该位于会话总线上。

在这种情况下,使用“系统”.service 单元是错误的——它应该放在“用户”目录中——并且将配置放在 /etc/dbus-1/system.d/ 中是无用的(都是因为会话总线实例看起来没有,因为会话总线实例一开始就没有名称限制)。
  • 另一方面,系统级服务(例如,作为 root 或专用守护进程帐户运行的东西)应该位于系统总线上。

  • 所以如果这是一个“用户级”程序,你应该做的是:

删除

/etc/dbus-1/system.d/org.example.dirswatcher.conf

配置文件。顾名思义,该目录仅适用于系统总线。 (会话总线默认没有总线名称限制,所以不需要这样的配置。)
  1. 将系统服务单元转换为
    用户

    服务单元 – 将其移至
  2. /etc/systemd/user
  3. (甚至移至

    ~/.config/systemd/user/);删除 User=

     参数;将 multi-user.target 更改为 
    default.target
    使用 
    systemctl --user ...

    控制服务。
  4. 另外,修复 
    org.exmaple

    中的拼写错误 – 目前,您的配置定义了一个总线名称,但服务声明了另一个总线名称。

可选地,


如果
您确实希望 D-Bus 能够“按需”启动服务,您需要创建一个 dbus-daemon

.service 文件(与 systemd .service 文件不同)将总线名称与特定的可执行文件和/或 systemd 服务相关联。

对于系统服务,这将进入
/usr/[local/]share/system-services/;对于用户级服务,子目录只是 services/

(它可能位于您的 ~/.local/share 中)。例如:

~/.local/share/dbus-1/services/org.example.dirswatcher.service
[D-BUS服务] 名称=org.example.dirswatcher # 用于直接(非 systemd)启动;必需的,但可能是 /bin/false 来要求 systemd Exec=/home/user/file-manager/daemon/dirswatcherd.py # 对于间接(systemd)启动;选修的 SystemdService=dirswatcherd.service
    

© www.soinside.com 2019 - 2024. All rights reserved.