0

I have created a SystemD unit to start a service, and that service requires another unit to start beforehand.

I've set the depending service with Requires=dependant.service, and that way when depending.service is automatically started during boot, it first tries to start dependant.service.

The problem is that if dependant.service starts too early, it fails to start (I'm not really sure what "too early" here means). To solve this, I've set dependant.service to Restart=always.

And that works fine - depending.service is enabled and starts automatically, it starts dependant.service, which crashes and then gets restarted and always succeeds to start on the 2nd try.

But depending.service have seen dependant.service's first failure and its Requires=dependant.service causes it to fail. The log shows:

systemd[1]: Dependency failed for depending.
systemd[1]: Job depending.service/start failed with result 'dependency'.

Even though dependant has eventually succeeded, and both have Restart=always, depending never restarts after the initial failure of dependant.

I've tried various configuration of Requires=, Wants=, BindsTo= and After but didn't manage to find a combination that causes depending to restart after dependant restarts.

  • Remember that you need Requires to set the dependency and then either After or Before to set the ordering (otherwise the ordering is undefined). Show us the [Unit] section of your two unit files? – larsks May 1 '18 at 14:43
1

It seems that the root cause is that dependant.service is starting too soon sometimes: adding Restart directives is a bit of a hack. This to me indicates that it's missing a timing requirement, which is what After is for. Depending on the type of service, you'll need to determine what resources are needed before the service should be started.

Assuming that this is network-related, you'll want to add the following in the [Unit] section of dependant.service:

After=network.target

By doing this, you're indicating that the basic network should be available before systemd tries to start the service. Otherwise, systemd will try to start as many services in parallel as it can, which means that depending on the start order you might be starting with basically nothing initialized, which is a situation that some services can tolerate and some fail badly with.

If you want to make sure that depending.service always restarts with dependant.service, then add both a BindsTo and After to depending.service:

[Unit]
After=dependant.service
BindsTo=dependant.service

These behaviours are documented in the systemd.unit(7) man page. I rarely have to use more than Wants, Requires and After, but there are more advanced options if you have services that have particularly complex start conditions.

I find it to be helpful when creating a new service (or group of services) to look in the distribution-supplied unit files to see how they are done and shamelessly copy the good parts (try /usr/lib/systemd/system or /lib/systemd/system): they often will have clues about what After and Requires requirements are useful for a particular type of service.

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.