Search code examples
linuxsystemddbus

Track outcome of startUnit dbus call to systemd


Context

I'm developing an application that performs dbus calls to manage systemd units. To get an idea for the calls, I'm writing a small shell script that should detect a failed unit like systemctl:

user$ systemctl --user start error-out.service
Job for error-out.service failed because ...

What I've tried

How to start a systemd unit is found in Using gdbus to start a systemd service. It works using StartUnit like this:

user$ dbus-send --session --print-reply --dest=org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager.StartUnit string:"error-out.service" string:"fail"

method return time=1736951345.318505 sender=:1.0 -> destination=:1.5481 serial=21872 reply_serial=2
   object path "/org/freedesktop/systemd1/job/63442"

Options for this call are explained in The D-Bus interface of systemd, but that document gives no examples at all. What's giving me trouble is getting the status of the job that's created. The docs say:

This can be achieved in a race-free manner by first subscribing to the JobRemoved() signal, then calling StartUnit() and using the returned job object to filter out unrelated JobRemoved() signals, until the desired one is received, which will then carry the result of the start operation

I understand what I should do, but how to do it is rather obscure to me, even after googling and reading the relevant parts of systemctl source code.

Question

How to monitor if a systemd unit failed, when starting the unit via the dbus interface?


Solution

  • Made it work for root user at least, while finishing the question. Still missing to make it work on the session bus, so all mentioned commands now require root.

    This dbus-monitor call shows the JobRemoved signals on the system bus:

    root# dbus-monitor --system "type='signal',sender='org.freedesktop.systemd1',interface='org.freedesktop.systemd1.Manager',member='JobRemoved'"
    
    signal time=1736954593.223214 sender=:1.5 -> destination=(null destination) serial=53301 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=JobRemoved
       uint32 63442
       object path "/org/freedesktop/systemd1/job/63442"
       string "error-out.service"
       string "failed"