I created PyQt5 program and a daemon using python. They should communicate via dbus - the program sends dbus-send --session --dest="org.example.dirswatcher" --type="method_call" --print-reply "/" "org.example.dirswatcher.update_dirs_to_watch"
and accordingly the update_dirs_to_watch
method from the daemon is executed. While I'm testing, everything works fine, but when I create a daemon from the dirswatcherd.py file and try to execute my PyQt5 app, it says Error org.freedesktop.DBus.Error.ServiceUnknown: The name org.example.dirswatcher was not provided by any .service files.
Yes, I did all of systemctl
stuff and the daemon has 'activating' status (sometimes when I was changing .service or .conf files the status was green but still no DBus service was provided)
What I also did is:
/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>
/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
ALSO. 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())
...
Your error message is kind of guiding you in the wrong direction. It implies two things – it says that 1) there's no service with such name currently running and that 2) D-Bus tried to start it "on demand" but didn't know how.
Although the second part is easy to fix (by creating a second, different kind of .service file), in your case that's not actually related to the problem you're solving – it's not a mandatory part of D-Bus; it's just an "on-demand start" mechanism, but that's not what you're doing. Your systemd config and even the service name imply that you want it to be permanently running, so you don't actually need to have D-Bus start it again. (And, besides that, the name "dirswatcherd" kind of implies that it should be a permanently running service, and therefore on-demand activation wouldn't really be suitable for it anyway.)
You should instead focus on the first part: the fact that there's no such service currently running, even though you tried to start it via systemd. You said that you only ever saw status "activating", which means that your service keeps crashing. If you see a service "activating" but it never goes to "active", the first thing you should do is check the systemd logs via journalctl -b -u dirswatcher
to see what's happening.
Most likely, what's happening is that your program is trying to connect to the session bus, but you're running it as a system service (and for some reason, adding .conf files for the system bus, even though that's not the same thing).
The key point is that system services have no access to the session bus. Not even if you set 'User=omen'. (Yes, they can be made to have access to one specific user's session bus, but the point is that you should not do that, even if it's possible.) In the same way, they don't have access to your GUI – that's also part of the "session".
(That's probably the reason you only ever saw "activating" and never "active" – the service kept failing to start because it had no bus access, and your 'Restart=always' just masked the problem.)
Generally, user-level services (e.g. stuff that runs under the invoker's user account, and especially stuff that interacts with X11/Wayland GUIs) should be on the session bus.
In that case, using a 'system' .service unit is wrong – it should go in the 'user' directory – and placing configuration in /etc/dbus-1/system.d/ is useless (both because the session bus instance doesn't look there, and because the session bus instance has no name restrictions to begin with).
On the other hand, system-level services (e.g. stuff that runs as root or as a dedicated daemon account) should be on the system bus.
So if this is a "user level" program, what you should do is:
Remove the /etc/dbus-1/system.d/org.example.dirswatcher.conf
configuration file. As the directory name implies, that's for the system bus only. (Session bus has no bus-name restrictions by default, so such configuration is not necessary.)
Convert the system .service unit to a user .service unit – move it to /etc/systemd/user
(or even to ~/.config/systemd/user/
); remove the User=
parameter; change multi-user.target to default.target
.
Use systemctl --user ...
to control the service.
Also, fix the typo in org.exmaple
– as it currently is, your configuration defines one bus name but the service claims another.
Optionally, if you actually want D-Bus to be able to start the service "on demand", you would need to create a dbus-daemon .service
file (different from systemd .service files) that associates the bus name with a particular executable and/or systemd service.
For system services, this would go in /usr/[local/]share/system-services/
; for user-level services the subdirectory is just services/
(and it may be located in your ~/.local/share). For example:
~/.local/share/dbus-1/services/org.example.dirswatcher.service
[D-BUS Service] Name=org.example.dirswatcher # For direct (non-systemd) start; required but may be /bin/false to require systemd Exec=/home/user/file-manager/daemon/dirswatcherd.py # For indirect (systemd) start; optional SystemdService=dirswatcherd.service