1

How can I trigger multiple systemd services when a dbus signal is lauched.

I'm trying to do so for org.freedesktop.hostname1 by creating a service like:

[Unit]
Description=Set host name

[Service]
ExecStart=/home/administrator/set-hostname
BusName=org.freedesktop.hostname1

After enabling it and run netplan apply the script is not executed.

TA.

Michael Hampton
  • 244,070
  • 43
  • 506
  • 972
jlanza
  • 113
  • 1
  • 2
  • 7
  • Congrats, you've run across something that's very poorly documented. I suggest looking at `/usr/share/dbus-1/system-services/org.freedesktop.hostname1.service` to start. – Michael Hampton Aug 09 '18 at 19:38

1 Answers1

2

I assume that by 'triggering' a service you want a new service to start running (which is something that systemd can do) instead of making an already running service do something (which is completely out of the init system's reach).

D-Bus basics

Each D-Bus message has exactly one 'recipient' field (which may be either a well-known name such as org.example, an unique name such as :1.234, or the broadcast address).

D-Bus signals (sent to publish events that already happened) are usually broadcast to the entire bus, so they cannot cause any services to be started. If you're thinking about unicast messages sent to a specific service, those are usually method_calls, not signals.

D-Bus service autostart

The bus daemon will automatically start services when:

  1. there is a message sent to a specific well-known name,
  2. and that well-known service isn't currently "claimed" on the bus,
  3. and that well-known name has a corresponding D-Bus .service file (not to be confused with systemd .service files) under /usr/share/dbus-1/system-services/.

It's important to note from point #2 that only one service may claim a well-known name and receive messages destined for that name. As long as the real systemd-hostnamed is already running and has claimed org.freedesktop.hostname1, it will receive those messages – other processes cannot do the same.

The same point #2 also means that autostart will not happen for names that a service is currently holding. The message will simply be delivered to that already-running service.

In point #3, file's name must exactly match the well-known bus name; i.e. you cannot have multiple services competing for autolaunch under the same name. Therefore, as far as dbus-daemon cares, each message can only start one service at most.

Autostart via systemd

If the D-Bus .service file (under /usr/share/dbus-1/…/) contains a SystemdService= option, dbus-daemon will attempt to start that service via systemd instead of traditionally forking/execing whatever is listed in Exec=.

(Often the systemd service installs an Alias named dbus-[busname].service – this is only a convention to allow for systemctl enabling/disabling, and the syntax has no special meaning beyond that.)

Since systemd services can have dependencies, you now have a workaround for the "each message can only start one service" limitation: the service being directly activated can pull in other services as dependencies. However, everything explained before still applies – once the 'real' service is running, further messages will reach it directly and will not trigger autostart.

Conclusion

It seems like you're trying to avoid systemd-hostnamed completely, and whenever netplan calls hostnamed's SetHostname() method, you want your own program to receive it.

This is not possible with a simple shell script. You cannot receive D-Bus messages via stdin, nor via environment variables, nor via command-line arguments. Your script will only know that it was started for some reason, but it will have no clue as to what it's supposed to be doing exactly.

But it is possible in general – as long as you use a programming language that has a D-Bus module. You "just" need to connect to the system bus, claim the name, receive messages, and handle them the same way systemd-hostnamed does. Many dbus modules come with "skeleton D-Bus service" examples.

(In fact there already are third-party reimplementations of various systemd daemons, e.g. LoginKit, systembsd, systemd-shim.)

user1686
  • 10,162
  • 1
  • 26
  • 42
  • Great explanation!!! Thanks a lot. I understand the system much better now. I implemented my solution taking another direction which consists on using an already running handler for D-Bus. So much like the idea you propose. Thanks a lot!!! – jlanza Aug 29 '18 at 19:08
  • Well, that's not exactly what I was proposing. If you intend to _completely replace_ systemd-hostnamed with your own implementation, you can still use autostart exactly the same way systemd-hostnamed uses it. – user1686 Aug 30 '18 at 05:15