1. Introduction

By default, Linux system services restart independently, except when configured otherwise. But then, there are times when we want two or more services to restart simultaneously because they are interdependent or one is a dependency on the other.

In this tutorial, we’ll describe how to configure system services to restart automatically when their dependents are restarted.

2. Using PartOf

PartOf is an option used in the [Unit] section of system service configurations. It basically configures one system unit to use another system unit as a dependency such that when the dependency restarts or stops, the configured unit restarts or stops. But the dependency will not restart or stop when the configured unit restarts or stops.

For instance, say we have two services foo.service and bar.service. If we want bar.service to restart or stop whenever foo.service restarts or stops, we’ll make foo.service a dependency of bar.service using PartOf. To do this, we’ll add PartOf=foo.service under the [Unit] section of bar.service.

Let’s illustrate PartOf using a Prometheus service with a Node Exporter dependency:

$ cat /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
Wants=network-online.target
After=network-online.target
PartOf=node_exporter.service
...truncated...

After editing prometheus.service, we’ll reload systemd manager configuration using systemctl daemon-reload. Then, we’ll restart prometheus.service.

After that, we’ll restart node_exporter.service and query its journal to see the time it restarted:

$ sudo systemctl restart node_exporter.service && sudo journalctl -ru node_exporter.service
-- Logs begin at Tue 2023-02-21 11:08:53 UTC, end at Sun 2023-06-25 12:02:39 UTC. --
Jun 25 12:02:39 ubuntu-focal systemd[1]: Started Node Exporter.
Jun 25 12:02:39 ubuntu-focal systemd[1]: Stopped Node Exporter.
Jun 25 12:02:39 ubuntu-focal systemd[1]: node_exporter.service: Succeeded.
Jun 25 12:02:39 ubuntu-focal systemd[1]: Stopping Node Exporter...
...truncated...

Using journalctl, we’ll query prometheus.service‘s journal to see when it restarted:

$ sudo journalctl -g 'Prometheus Server' -ru prometheus.service
-- Logs begin at Tue 2023-02-21 11:08:53 UTC, end at Sun 2023-06-25 12:09:48 UTC. --
Jun 25 12:02:39 ubuntu-focal prometheus[8361]: ts=2023-06-25T12:02:39.875Z caller=main.go:578 level=info msg="Starting >
Jun 25 12:02:39 ubuntu-focal systemd[1]: Started Prometheus Server.
Jun 25 12:02:39 ubuntu-focal systemd[1]: Stopped Prometheus Server.
Jun 25 12:02:39 ubuntu-focal systemd[1]: Stopping Prometheus Server...
...truncated...

From the output of both journal queries, we can see that prometheus.service restarted at the same time as node_exporter.service12:02:39.

When querying prometheus.service‘s journal, we added -g ‘Prometheus Server’ to restrict the output of the journal query to logs containing the string, “Prometheus Server”. Without it, we would have had to scroll through a long list of logs before finding what we wanted.

3. Using BindsTo

BindsTo is another option used in the [Unit] section of system service configurations. It configures a system unit to use another system unit as a dependency such that when the dependency restarts or stops, the configured unit does the same. However, the reverse does not apply.

Also*,* with BindsTo, when the configured unit starts (goes from inactive to active), the dependency – if it was inactive – will also start. Yet again, the reverse does not apply.

If we want to ensure that the configured unit is only active when the dependency is active, we’ll pass the name of the dependency to BindsTo and After while setting up the configured unit.

Let’s cat into our unit file where prometheus.service binds to node_exporter.service:

$ cat /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
Wants=network-online.target
After=network-online.target
BindsTo=node_exporter.service
...truncated...

After binding prometheus.service to node_exporter.service, if we restart node_exporter.service, prometheus.service will restart automatically. We can confirm this by checking the logs of both services.

4. Using Requires

Like PartOf and BindsToRequires is an option used in the [Unit] section of system service configurations. Requires and BindsTo have very similar use cases. For one, both of them set the configured unit up to restart or stop when the dependency restarts or stops.

However, when used with After, BindsTo can ensure the configured unit is only active when the dependency is active. Requires, on the other hand, does not require the dependency to be active for the configured unit to remain active.

Let’s make prometheus.service require node_exporter.service:

$ cat /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
Wants=network-online.target
After=network-online.target
Requires=node_exporter.service
...truncated...

With the new configuration, when we restart node_exporter.serviceprometheus.service will also restart. Of course, before restarting node_exporter.service, we’ll reload the systemd manager configuration and restart prometheus.service for the configuration to take effect.

5. Conclusion

To restart a service automatically when its dependent restarts, we can define the service’s dependent using PartOf, BindsTo, or Requires.

Of all three system unit properties, BindsTo has the fewest limitations (it offers more features than the other two). PartOf, on the other hand, is the most limited – it only configures a service to restart or stop when its dependency restarts or stops.