We already mentioned Instantiated Services a few times. However, there is one question we did not yet cover:
How to hook up those instances with our package manager
For a normal service file this is pretty easy. Such a service can be handled as follow in the spec file:
%pre %service_add_pre superduper.service %post %service_add_post superduper.service %preun %service_del_preun superduper.service %postun %service_del_postun superduper.service
That is it. It will do all the things we want.
But our instantiated services are launched with a parameter like in the following example:
systemctl start superduper@bar
We could parse the output of
systemctl status, find all instances and then restart them in a loop. But there is a better way.
Painting a target
Assuming the base superduper@.service file looks like following:
[Unit] Description=Super Duper Daemon Wants=network-online.target After=network-online.target [Service] Type=simple ExecStart=/usr/sbin/superduper --config /etc/superduper/%i.conf [Install] WantedBy=multi-user.target
%i part in the
ExecStart= line holds the parameter passed to the unit file.
PartOf= statement in the
[Unit] section of the service file we declare that this unit file sees itself as part of the group.
The superduper@.service file now looks like this.
[Unit] Description=Super Duper Daemon Wants=network-online.target After=network-online.target PartOf=superduper.target [Service] Type=simple ExecStart=/usr/sbin/superduper --config /etc/superduper/%i.conf [Install] WantedBy=multi-user.target
The corresponding target file is really simple:
[Unit] Description=All instances of Super Duper Daemon
Now we can manually do the following actions:
systemctl stop superduper.target systemctl restart superduper.target
You can not start all services with a target. This has to be done manually again. Restart and stop are the only working actions. Now our RPM integration becomes:
%preun %service_del_preun superduper.target %postun %service_del_postun superduper.target
We can’t really handle that the macros for %pre and %post do with target files.
Targetting other things
It is worth mentioning that you can use the whole mechanism also with non instantiated services. We use it for example with our discourse package to restart the puma app server and sidekiq after an update.
Until we get a clean solution to disable services via the following snippet, we need a temporary solution.
%preun %service_del_preun superduper.target
We learned that
systemctl disable superduper@.service works.
%preun %service_del_preun superduper.target superduper@.service
The target will take care that the service gets shutdown, and the 2nd service reference will work for disabling the service. Of course this is a little ugly has 2 “noops” in it … the stop call will not work with the service part and the disable part will not work with the target.
But still some progress.
- check if
foo@.targetas seen in brltty makes sense
- check how to handle %preun service disable with instantiated services is %service_del_preun foo@.service working as expected? seems we might need a working systemctl disable foo.target for that.