天天看點

How to write a service unit file which enforces that particular services have to be started

Red Hat Enterprise Linux 7

systemd

​<code>​After=/Before=​</code>​ options don't guarantee the listed units has been started and running. How do I write a service unit file which enforces that particular services have to be started?

On RHEL7, a service unit file needs to specify its dependencies using ​<code>​After=/Before=​</code>​ options. This ensures that (if configured that way) that, for example, ​<code>​b.service​</code>​ will be started after ​<code>​a.service​</code>​. What it does not do is ensure that ​<code>​b.service​</code>​ is only started if ​<code>​a.service​</code>​ is successfully started. This is because the ​<code>​After=/Before=​</code>​ options just specify the order of dependencies. Any ​<code>​After=/Before=​</code>​ does not care about if the dependency is running or not.

If a service requires that the dependent services have to be running, you need to consider the options listed below to satisfy that requirement.

A ​<code>​[Unit]​</code>​ section of a service configuration file can contain following options which enforce a requirement that the listed units must be started and running. The details are quoted from ​<code>​man 5 systemd.unit​</code>​.

​​Raw​​

The details of <code>Requires=</code>

This option configures requirement dependencies on other units. If this unit gets activated, the units listed here will be activated as well. If one of the other units gets deactivated or its activation fails, this unit will be deactivated. This option may be specified more than once or multiple space-separated units may be specified in one option in which case requirement dependencies for all listed names will be created. Note that requirement dependencies do not influence the order in which services are started or stopped. This has to be configured independently with the <code>After=</code> or <code>Before=</code> options. If a unit <code>foo.service</code> requires a unit <code>bar.service</code> as configured with <code>Requires=</code> and no ordering is configured with <code>After=</code> or <code>Before=</code>, then both units will be started simultaneously and without any delay between them if <code>foo.service</code> is activated. Often it is a better choice to use <code>Wants=</code> instead of <code>Requires=</code> in order to achieve a system that is more robust when dealing with failing services.

The details of <code>Requisite=</code>

This option is similar to <code>Requires=</code> respectively. However, if the units listed here are not started already, they will not be started and the transaction will fail immediately.

The details of <code>PartOf=</code>

This option configures dependencies similar to <code>Requires=</code>, 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.

This section provides some guidance on how to choose the appropriate keyword(s) in your unit file(s). In the following, we assume a.service and b.service have their dependencies as described below.

When <code>b.service</code> is activated, <code>a.service</code> should be activated also (if not already). The unit <code>a.service</code> must start successfully - if it fails or is deactivated <code>b.service</code> will also be deactivated.

You should use <code>Requires=</code> to activate <code>a.service</code> and ensure <code>b.service</code> cannot start unless <code>a.service</code> starts.

If <code>a.service</code> is not started already, <code>b.service</code> should not be started and will fail immediately. The activation of <code>a.service</code> should not be triggered by the activation of <code>b.service</code>.

You should use <code>Requisite=</code> to fulfill the requirement.

<code>b.service</code> always needs to be activated after <code>a.service</code> is activated. But <code>a.service</code> should not be activated when <code>b.service</code> is activated however <code>a.service</code> does need to be stopped or restarted when <code>b.service</code> is stopped or restarted.

You should use <code>PartOf=</code> in this situation.

You may need to use multiple keywords to achieve a desired outcome. For example, you may have <code>b.service</code> with <code>Requires=a.service</code> so <code>b.service</code> will not start unless <code>a.service</code> starts and starting <code>b.service</code> starts <code>a.service</code> first. As well in the definition of <code>a.service</code> you might need <code>PartOf=b.service</code> so if <code>b.service</code> is stopped or restarted <code>a.service</code> will have the same action taken on it.

Complex interactions between units can be achieved but requires you to plan out what interactions are required. For other options, please refer to <code>man 5 systemd.unit</code>.

繼續閱讀