1

I'm trying to rewrite an init script to systemd, but I'm struggling with an issue of optional dependencies.

My service depends (optionally) on two other services. These two dependencies are mutually exclusive (server and client package) - only one can be installed at a time, and can be missing completely.

If either of the dependencies is installed, the dependency should be started before my service, and if the start fails, my service should not start.

But if neither of the dependencies is installed, my service should start normally.

How can I achieve this functionality? Optional dependencies are handled through Wants=, but this ignores errors.

  • Please do clarify.Your service depends on the package installation or on starting of the other services? – Thushi Aug 17 '15 at 12:09
  • @WitchDoctor I explicitly wrote "they should be started and if the start fails, the service should not start". You could technically check for installed files in a systemd service description, but that would be pretty ridiculous. – Let_Me_Be Aug 17 '15 at 12:16
  • Yeah. So your service depends on other two services. And either one of them start fails then your service should not start. And if both the services start then your service should start normally. Am I right? – Thushi Aug 17 '15 at 12:22
  • @WitchDoctor OMG, seriously read the question. On each machine, there will be either none of the dependencies installed, in which case, the service should start normally, or there will be one of them installed (since they conflict with each other), in which case, it should be treated as a hard dependency (do not start the service on fail). – Let_Me_Be Aug 17 '15 at 12:31
  • Now I got it. Thanks. Anyhow I will just confirm. If the dependency is installed then it should start before your service and by chance if it fails your service should not start and if the dependency service is not installed at all then your service should start normally.Right? :) – Thushi Aug 17 '15 at 13:45
1

If you have control over the dependencies (i. e. they are your software), make them install a drop-in file for the unit file in question. That is, let's say you have foo.service which needs to depend on bar.service || baz.service.

Then the bar package can install a file /usr/lib/systemd/system/foo.service.d/50-bar-baz.conf with these contents:

[Unit]
Requires=bar.service

Similarly for baz package.


If you have no control over the dependencies, then simply make a "dispatcher" script which checks unit files for existence and then does an exec systemctl start on the chosen unit file. Then write a separate unit and require/after it from the main unit:

[Unit]
# inexistent unit names are ignored here
After=bar.service baz.service

[Service]
Type=oneshot
ExecStart=/path/to/dispatcher
  • I'm not OP, but I had the exact same requirement, and your first solution is exactly what I needed. Don't know why I didn't think of that. I'd mark your answer as accepted if this was my question, but alas... Thanks! – Aaron Burke Sep 13 '17 at 0:09
-1

You can use the systemd path units for that.Your service file should have a corresponding path unit to check for the path/file exists or not.

Example:

service.path
[Unit]
Description:Service description

[Path]
PathExists=!/other/service/binary/path/or/some/other/file/from/that/package

[Install]
WantedBy=some-user.target

This one will activate your service only if the mentioned file exists.

  • I have tried to reformulate the question for more clarity. But this is pretty much as clear as I can make it. – Let_Me_Be Aug 17 '15 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.