42

A service (say bar.service) is dependent on another service (say foo.service), like below

bar's service file:

[Unit]
After=foo.service
Requires=foo.service
...

If foo.service is restarted (either manually or due to a bug), how can bar.service be automatically restarted as well?

iobelix
  • 1,143
  • 1
  • 10
  • 16
  • 1
    Have you tried to put the line 'Restart=always' in your service ? I guess bar should be restarted as soon as its dependency is alive – ogs Mar 16 '16 at 22:08
  • 4
    @SnP Restart "Configures whether the service shall be restarted when the service process exits, is killed, or a timeout is reached" and thus would not help unless bar crashes when foo restarts. – Kevin M Granger Mar 16 '16 at 22:12
  • Quite interesting ! Thank for the clarification – ogs Mar 16 '16 at 22:16

3 Answers3

58

You can use PartOf.

[Unit]
After=foo.service
Requires=foo.service
PartOf=foo.service

From the systemd.unit man page:

PartOf=

Configures dependencies similar to Requires=, but limited to stopping and restarting of units. When systemd stops or restarts the units listed here, the action is propagated to this unit. Note that this is a one-way dependency — changes to this unit do not affect the listed units.

Community
  • 1
  • 1
Kevin M Granger
  • 2,375
  • 23
  • 28
  • 14
    Note that `PartOf` only links restarting, but **not stop, upgrade, start** events. In those cases you may need `WantedBy`. [See this answer for details](https://unix.stackexchange.com/questions/375091/how-to-get-my-systemd-service-restarted-when-its-dependency-is-upgraded) – Rennex Jul 21 '17 at 13:10
  • 1
    it doesn't link stop events? It says twice in the definition above that it does: `When systemd stops or restarts the units listed here, the action is propagated to this unit` – jdizzle Apr 18 '19 at 01:10
  • @jdizzle The documentation can write what it wants, the behaviour is clearly different. I tried it out. The dependent service is restarted with foo, but it is not started after foo if foo was explicitly stopped before. It just remains stopped. So the `PartOf` is good for automatic updates or config updates of foo, but nothing more. – ygoe Dec 15 '20 at 21:31
  • @ygoe Yes, it only links stops and restarts. Not starts. For that, you need `Wants` or `Requires`. – Kevin M Granger Dec 15 '20 at 22:53
  • I think @ego2dot0's answer below should be the accepted answer. `BindsTo` is exactly what I needed. In my case, I want my service to be only active if `postgresql` is active, and the docs of `BindsTo` say: "Use the BindsTo= dependency type together with After= to ensure that a unit may never be in active state without a specific other unit also in active state (see below)." – Bernhard Schussek Mar 11 '22 at 07:49
  • @BernhardSchussek that does indeed sound like it's better for your use case. However, your use case is not what the original question was. It would be perfectly valid to create a new question for that though! – Kevin M Granger Mar 11 '22 at 21:31
9

A another solution might be to use ExecStartPost option to restart the bar.service (if it´s executed) when foo.service has (re)started:

# foo.service
[Service]
ExecStartPost=/bin/systemctl try-restart bar.service
Restart=on-failure
RestartSec=30s

The additional Restart and RestartSec options ensure that foo.service will automatically restarted on crash and thus also bar.service.

A second extension my be to add same to bar.service and ensure that bar.service start after foo.service:

# bar.service
[Unit]
After=foo.service

[Service]
Restart=on-failure
RestartSec=30s

This should start both services automatically in case of a crash and bar.service will be restarted when foo.service restarts (due to an error or manually triggered).

panticz
  • 2,135
  • 25
  • 16
8

I think the needed option is BindsTo, it handles the misbehaviours too.

[Unit]
Requires=postgresql.service
After=postgresql.service
BindsTo=postgresql.service

BindsTo=

Configures requirement dependencies, very similar in style to Requires=. However, this dependency type is stronger: in addition to the effect of Requires= it declares that if the unit bound to is stopped, this unit will be stopped too. This means a unit bound to another unit that suddenly enters inactive state will be stopped too. Units can suddenly, unexpectedly enter inactive state for different reasons: the main process of a service unit might terminate on its own choice, the backing device of a device unit might be unplugged or the mount point of a mount unit might be unmounted without involvement of the system and service manager.

When used in conjunction with After= on the same unit the behaviour of BindsTo= is even stronger. In this case, the unit bound to strictly has to be in active state for this unit to also be in active state. This not only means a unit bound to another unit that suddenly enters inactive state, but also one that is bound to another unit that gets skipped due to a failed condition check (such as ConditionPathExists=, ConditionPathIsSymbolicLink=, … — see below) will be stopped, should it be running. Hence, in many cases it is best to combine BindsTo= with After=.

ego2dot0
  • 429
  • 4
  • 13
  • My experience is that the unit does not restart with BindsTo. It only stop. But when using PartOf it did both stop and restart. – BrnVrn May 21 '18 at 09:43
  • 1
    Yet, starting requires to have the `WantedBy=foo.service` directive in `[Install]` as pointed out by @Rennex – BrnVrn May 21 '18 at 10:05
  • @BrnVm WantedBy is another dependency. Your MyService is not a dependency of Postgres, but otherwise. I don't want to start MyService, whenever Postgres is started. I just want to restart MyService whenever Postgres dies or is restartet. Requires and After handles the dependencies to Postgres and BindsTo the restart of MyService. – ego2dot0 May 29 '18 at 20:48
  • This should be the accepted answer IMO. – Bernhard Schussek Mar 11 '22 at 07:50