19

I have a service foo.service which depends on service bar.service. I need to make sure that bar.service is started before foo.service and that bar.service launched successfully.

From this source it says that Requires:

This directive lists any units upon which this unit essentially depends. If the current unit is activated, the units listed here must successfully activate as well, else this unit will fail. These units are started in parallel with the current unit by default.

and that After:

The units listed in this directive will be started before starting the current unit. This does not imply a dependency relationship and one must be established through the above directives if this is required.

Is it correct to have both the Requires and After sections in the same unit file? Requires says that the service will be launched in parallel, but After says it will be launched before. If bar.service fails to start during the After condition, will it attempt to launch it again during the Requires section? If so I need to find another way to launch foo.service

foo.service

[Unit]
After=bar.service
Requires=bar.service
flakes
  • 21,558
  • 8
  • 41
  • 88
  • Using both `Requires` (or `Wants` for that matter) and `After` should be what you're looking for. That enforces the order (`After`) and the dependency (`Requires`). It won't launch it again "during the `Requires` section" (note as well that service files are not executed but parsed). – Whymarrh Nov 14 '16 at 16:33
  • @Whymarrh okay so I assume that means having both directives will change the "default" startup mentioned in the `Requires` description; "started in parallel with the current unit by default" – flakes Nov 14 '16 at 16:39
  • 1
    Yes, see also: [`Requires=`](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Requires=) – Whymarrh Nov 14 '16 at 16:42
  • I’m voting to close this question because it belongs to unix.stackexchange.com – raspi Jun 15 '22 at 06:01

2 Answers2

19

It is perfectly fine to use both After= and Requires=. They have different purposes. Requires= sets up a start dependency. systemd makes sure that if any body is trying to start foo.service, it should start bar.service too. Should bar.service fails at some point, then foo.service is taken down too.

After= is putting a start order between services. If both of the services are scheduled to start, then After= makes sure the start order is set.

You can look at systemd's own service file as an example.

/lib/systemd/system/basic.target
[Unit]
...
Requires=sysinit.target
After=sysinit.target
...
Umut
  • 2,317
  • 1
  • 17
  • 19
  • what about WantedBy? in /etc/systemd/system/default.target.wants/watchdog.service: [Unit] After=multi-user.target [Install] WantedBy=multi-user.target – vvigilante Mar 18 '20 at 17:06
10

While Umut's answer is correct, there is an interaction between Requires= and After= that is rarely spelled out. From systemd.unit#Requires= (emphasis is mine):

If this unit gets activated, the units listed will be activated as well. If one of the other units fails to activate, and an ordering dependency After= on the failing unit is set, this unit will not be started.

Essentially, this means that without After=, both services will be started if foo.service is started (because of Requires=), but systemd will not stop foo.service if bar.service does not start successfully.

However, with the added After=, it will wait for bar.service to start successfully (with some exceptions; see the note in the Requires= docs) before it starts foo.service and won't start it if bar.service doesn't start.

Somewhat related is the difference between Requires= and BindsTo= (see the docs around the link above).

Gerhard
  • 518
  • 5
  • 9