I am creating a package foo
which launches/closes upstream package bar
. The relationship should be:
- When you start foo, also start bar.
- When to you stop/reload foo, also stop/reload bar.
bar
may be started, stopped or reloaded without affectingfoo
If /lib/systemd/system/bar.service
looks like this:
[Unit]
Description=Bar
[Service]
ExecStart=/bin/sleep infinity
Restart=on-failure
Then then "normal" solution would be to add WantedBy
and PartOf
relationships to bar
:
[Unit]
Description=Bar
PartOf=foo.service
[Service]
ExecStart=/bin/sleep infinity
Restart=on-failure
[Install]
WantedBy=foo.service
However, bar
is an upstream package and I think it's not quite right to force bar
to be aware of foo
, or to patch bar
.
I thought a perfect solution would be to create foo.service
like this:
[Unit]
Description=Foo
Wants=bar.service
ConsistsOf=bar.service
[Service]
Type=oneshot
ExecStart=/bin/true
RemainAfterExit=yes
However my journalctl says:
Unknown lvalue 'ConsistsOf' in section 'Unit'
and man pages say:
When PartOf=b.service is used on a.service, this dependency will show as ConsistsOf=a.service in property listing of b.service. ConsistsOf= dependency cannot be specified directly.
I'm not sure why ConsistsOf=
cannot be specified directly, but is there an alternative that I didn't consider?
Best Answer
The appropriate way to modify upstream/external bar.service to include a
PartOf=
relationship to another unit is to use a "drop-in" override config, which is a systemd feature allowing you to modify existing units without having to touch the original files.From systemd.unit man page:
In your particular case, you should create a drop-in such as
/etc/systemd/system/bar.service.d/partof-foo.conf
, with contents:(The name
partof-foo.conf
is just a suggestion, anything with a.conf
suffix should work.)Then reload the daemon with
systemctl daemon-reload
.After that is done, you can inspect the unit with
systemctl cat bar
, which will neatly show the override is being taken into account. Also, now,systemctl show foo
will show aConsistsOf=
relationship tobar.service
and the effects of that relationship will follow (stoppingfoo
will causebar
to stop.)For the second part (
foo
havingWants=bar.service
), I suggest adding that directive directly tofoo.service
instead of using an[Install]
stanza in an "drop-in" forbar.service
.For one, the
[Install]
section would have to be activated with asystemctl enable bar
command, so in a way it's harder to maintain. (Also, I've seen bugs where[Install]
from a "drop-in" is not respected. I believe these have been fixed, but might still exist in your distro's version of systemd.)Furthermore, you might want to use a stronger
Requires=
relationship, rather thanWants=
, since that will makefoo.service
fail ifbar.service
can't be started. (Consider also adding an ordering dependency, such asAfter=bar.service
fromfoo.service
, sofoo
will actually wait untilbar
is up before doing its own startup.)Since
foo.service
is a file you control, simply include it there directly:That's assuming you'll want the ordering dependency as well, it's safe to omit it if you don't.
That should take care of everything.