https://access.redhat.com/solutions/3120581
SOLUTION 已验证 - 已更新 2017年七月20日15:22 -
环境
- Red Hat Enterprise Linux 7
- systemd
问题
After=/Before=
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?
决议
Background:
On RHEL7, a service unit file needs to specify its dependencies using After=/Before=
options. This ensures that (if configured that way) that, for example, b.service
will be started after a.service
. What it does not do is ensure that b.service
is only started if a.service
is successfully started. This is because the After=/Before=
options just specify the order of dependencies. Any After=/Before=
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.
Detailed information:
A [Unit]
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 man 5 systemd.unit
.
Requires=
Requisite=
PartOf=
-
The details of
Requires=
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 theAfter=
orBefore=
options. If a unitfoo.service
requires a unitbar.service
as configured withRequires=
and no ordering is configured withAfter=
orBefore=
, then both units will be started simultaneously and without any delay between them iffoo.service
is activated. Often it is a better choice to useWants=
instead ofRequires=
in order to achieve a system that is more robust when dealing with failing services. -
The details of
Requisite=
This option is similar toRequires=
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
PartOf=
This option configures dependencies similar toRequires=
, 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.
How do I choose which option preferred to my unit file?
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.
a.service (Before=b.service)
b.service (After=a.service)
-
When
b.service
is activated,a.service
should be activated also (if not already). The unita.service
must start successfully - if it fails or is deactivatedb.service
will also be deactivated.
You should useRequires=
to activatea.service
and ensureb.service
cannot start unlessa.service
starts. -
If
a.service
is not started already,b.service
should not be started and will fail immediately. The activation ofa.service
should not be triggered by the activation ofb.service
.
You should useRequisite=
to fulfill the requirement. -
b.service
always needs to be activated aftera.service
is activated. Buta.service
should not be activated whenb.service
is activated howevera.service
does need to be stopped or restarted whenb.service
is stopped or restarted.
You should usePartOf=
in this situation.You may need to use multiple keywords to achieve a desired outcome. For example, you may have
b.service
withRequires=a.service
sob.service
will not start unlessa.service
starts and startingb.service
startsa.service
first. As well in the definition ofa.service
you might needPartOf=b.service
so ifb.service
is stopped or restarteda.service
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
man 5 systemd.unit
.