I'm creating a systemd .service file and I need help understanding the difference between Requires=
and After=
. The man page says that Requires=
"Configures requirement dependencies on other units." and After=
"Configures ordering dependencies between units." What's the difference?
6 Answers
After=
configures service order (do X only after Y), while Requires=
state dependencies.
If you don't specify an order, a service depending on another would be started at the same time as the one it is depending on.
Also, the way I understand it (although I can't test that now and don't find a reference), After=
is "loose coupling", which effectively means that a service with an After
statement would still run even if the one named in the After=
line isn't started at all, while Requires=
would prevent its start if the requirement isn't met.
Citing https://www.freedesktop.org/software/systemd/man/systemd.unit.html:
Requires=
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 After= or Before= options. If a unit foo.service requires a unit bar.service as configured with Requires= and no ordering is configured with After= or Before=, then both units will be started simultaneously and without any delay between them if foo.service is activated. Often, it is a better choice to use Wants= instead of Requires= in order to achieve a system that is more robust when dealing with failing services.
and
Before=, After=
A space-separated list of unit names. Configures ordering dependencies between units. If a unit foo.service contains a setting Before=bar.service and both units are being started, bar.service's start-up is delayed until foo.service is started up. Note that this setting is independent of and orthogonal to the requirement dependencies as configured by Requires=. It is a common pattern to include a unit name in both the After= and Requires= option, in which case the unit listed will be started before the unit that is configured with these options. This option may be specified more than once, in which case ordering dependencies for all listed names are created. After= is the inverse of Before=, i.e. while After= ensures that the configured unit is started after the listed unit finished starting up, Before= ensures the opposite, i.e. that the configured unit is fully started up before the listed unit is started. Note that when two units with an ordering dependency between them are shut down, the inverse of the start-up order is applied. i.e. if a unit is configured with After= on another unit, the former is stopped before the latter if both are shut down. Given two units with any ordering dependency between them, if one unit is shut down and the other is started up, the shutdown is ordered before the start-up. It doesn't matter if the ordering dependency is After= or Before=. It also doesn't matter which of the two is shut down, as long as one is shut down and the other is started up. The shutdown is ordered before the start-up in all cases. If two units have no ordering dependencies between them, they are shut down or started up simultaneously, and no ordering takes place.
-
25What is a dependency if not a statement of order? (seriously... I don't understand the difference) Commented Nov 1, 2016 at 20:29
-
7See my edit. My understanding:
After=X
would mean "Do this after X if X is done", whileRequire=X
would mean "don't do this at all if you can't do X".– SvenCommented Nov 1, 2016 at 20:32 -
2The
Before=
section of the man page seems to confirm this.If a unit foo.service contains a setting Before=bar.service and both units are being started, bar.service's start-up is delayed until foo.service is started up
The way I understand that, the ordering wouldn't be enforced ifbar.service
isn't started anyway andfoo.service
would start normally.– SvenCommented Nov 1, 2016 at 20:39 -
1@TomOnTime „What is a dependency if not a statement of order“ – the key point is there's many things to be ordered, not just startup propagation! Stop propagation, propagation of failed / inactive states etc. may in general be configured differently to make your system more resilient against state changes. Sure, your login may require an LDAP connection, but plugging off the ethernet cable should not terminate your running session. The startup should propagate back, but the failure should not propagate forward. So we can't only have one dependency graph / one ordering, we need many. Commented Apr 15, 2022 at 11:36
One of the major difference is,
After
only checks if the unit is activated already, and does not explicitly activate the specified units.- The units listed in
Requires
are activated together with the unit. If any of the required units fail to start, the unit is not activated.
Consider I have a unit file test-app.service
,
[Unit]
Description=test app
After=network-online.target
Here is what will happen when this statement is executed,
After
checks ifnetwork-online.target
.- if
network-online.target
not started, it will wait. test-app
starts only afternetwork-online.target
is active
If I had Requires
instead,
[Unit]
Description=test app
Requires=network-online.target
Here is what will happen when this statement is executed,
network-online.target
andtest-app
are activated together- if
network-online.target
fails to starttest-app
will not be activated.
-
2You say
After
“does not explicitly activate the specified units.” Does that mean that withAfter
and noWants
orRequires
, the dependency may never start, and thus our service may never start?– JacktoseCommented Nov 6, 2021 at 1:16 -
1
systemd is a job manager. The man page is not very precise as to how things work.
When you boot, what systemd does is build a transaction comprising of jobs for the anchor job (i.e. start job for default.target). What all these dependencies and relationships do is define how and what jobs will be triggered. Ordering defines what job(s) every other job will wait on. The default.target unit hence is at the centre of all this, which is why when enabling units you use a reverse dependency which through systemctl enable creates a filesystem symbolic link denoting a forward dependency systemd can follow (also why you need filesystem symlinks in the first place). Similar is when you manually start some unit, then that unit is anchor, and transaction is computed wrt it.
Not going in too much detail, I'll explain what Requires= and After= does.
Requires= will cause systemd to trigger a start job for the required unit when you get a start job triggered (explicitly, or through a dependency: there is no distinction internally). It also has the property of triggering a stop job on you when this unit is stopped (note: stopped, not going down on its own) or restarted. This means that if some dependency/systemctl causes it to stop/restart, you will also stop/restart. However, if it goes down on its own, you will not stop, as there was no job, and the state change happened without systemd's involvement. That's where you would use BindsTo= (similar to device units, which can go to inactive without systemd's involvement, for obvious reasons).
Now, the use of After= is recommended as Requires= alone is racy for what it does: cancel the requiree if the start job fails. This cancellation however only works wrt jobs, i.e. if the other unit does not define ordering, systemd triggers both in parallel, and if its start job finishes before your start job fails, it will not be cancelled (it cannot be cancelled, in fact). Use of After= means that other job keeps waiting until the start job of the required unit finishes, and depending on the result, if it failed, your unit's waiting start job is cancelled with the JOB_DEPENDENCY job result (why you use yellow [DEPEND] at boot for such cases). Hence, this invalidation effect is undeterministic without use of After=.
This is why using Wants= without After= is fine if you don't want to wait for the startup of the other unit: as there is no invalidation there, so there is no race. In that case, it is no more than a synchronization mechanism.
Also, you can also enable both at boot, and not require one another, and only define ordering, in that case, when both are pulled as part of the same transaction, they will be ordered (or if the job for the other is triggered while the job for the unit it wants to run after is running, it will first wait for it finish, across transactions).
Now if there is no job, ordering has no effect for the said unit. However, there usually is a job, as a consequence of use of dependencies like Requires= and Wants=, or both getting pulled in at a time and define some ordering, in which case they do wait on the another unit's job(s).
-
3It sounds like
After
impliesRequires
. Can I useAfter
alone, with outRequires
/Wants
?– JacktoseCommented Nov 6, 2021 at 1:17 -
1@Jacktose If you do that, and you start the service with an
After
, and the service IN theAfter
isn't already started, it will not be automatically started. For that you'll needRequires
orWants
, which is precisely why these two options are often used together.– AradCommented Nov 18, 2022 at 20:37
Ref link: https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
I did few tests, may be it will be helpful to understand the practical results of how "Requires=", "After=" and "Wants=" works. "Requires=": used for tight coupling. If require unit fails at startup or in between, current unit will also stop/crash/fails. "After=" : used for loose coupling and decides order. If require unit fails in between, current unit has no impact on this.
Defining UnitBasic.service, which need UnitChecker to be started first. Sample Test cases:
After=UnitChecker
Requires=UnitChecker
Result:
ip: stop UnitChecker
stop UnitBasic
start UnitBasic
op: UnitChecker gets start
UnitBasic gets start => both active, first UnitChecker(pid:1) then UnitBasic(pid:2)
ip: stop UnitBasic
op: UnitBasic gets stop
UnitBasic remains active => No impact on UnitChecker
ip: stop UnitChecker
op: UnitChecker gets stop
UnitBasic remains stop => both inactive now
ip: start UnitBasic
UnitBasic gets start
UnitChecker gets start => both active now
ip: stop UnitChecker
UnitBasic gets stop
UnitChecker gets stop => both inactive now because ofdependency on UnitChecker
ip: start UnitChecker
op: UnitChecker gets start
UnitBasic remians stop => Only UnitChecker active
ip: start UnitBasic
op: UnitChecker remians start
UnitBasic gets start => both active now, UnitChecker(pid:1) then UnitBasic(pid:2)
Requires= tight coupling, if dep service stops, this service will also get stop.
If dep service is not started, it will start the service mentioned in "Requires"
systemctl daemon-reload
Result:
ip: stop UnitBasic
stop UnitChecker
systemctl start UnitBasic
op: UnitBasic starts
UnitChecker starts => both starts, first UnitBasic(pid:1) then start(pid:2)
ip: stop UnitChecker
op: UnitChecker gets stop
UnitBasic gets stop => both inactive
ip: stop UnitBasic
stop UnitChecker
systemctl start UnitBasic
op: UnitBasic starts
UnitChecker starts => both starts, first UnitBasic(pid:1) then start(pid:2)
ip: stop UnitBasic
op: UnitBasic gets stop
UnitChecker remains active
Conclusion: dependent unit is not having any dependency on the unit, which is using it(UnitBasic).
After: Loose coupling
Result:
ip: stop UnitChecker
stop UnitBasic
start UnitBasic
op: UnitBasic gets start
UnitChecker remains stop
ip: start UnitChecker
op: UnitChecker gets start
UnitBasic remains start => both active now
ip: stop UnitChecker
op: UnitChecker gets stop
UnitBasic remains active => no impact on UnitBasic
UnitBasic.service
Wants: Loose coupling
Result:
ip: stop UnitChecker
stop UnitBasic
start UnitBasic
op: UnitChecker gets start
UnitBasic gets start => both active, first UnitBasic(pid:1) then UnitChecker(pid:2)
ip: stop UnitChecker
op: UnitChecker gets stop
UnitBasic remains active => Only dependent unit: UnitChecker getting inactive
ip: stop UnitChecker
stop UnitBasic
start UnitBasic
op: UnitChecker gets start
UnitBasic gets start => both active, first UnitBasic(pid:1) then UnitChecker(pid:2)
ip: stop UnitBasic
UnitBasic gets stop
UnitChecker remains active => no impact on UnitChecker
Again ip: stop UnitChecker
stop UnitBasic
start UnitBasic
op: UnitChecker gets start
UnitBasic gets start => both active, first UnitBasic(pid:1) then UnitChecker(pid:2)
ip: stop UnitChecker
op: UnitChecker gets inactive
UnitBasic remains active => no impact on UnitBasic, So here UnitBasic don't have dependency on UnitChecker
We have use "After=" with "Wants=", if we want the specific order that dependent service(UnitChecker) should start first then using service (UnitBasic).
And if any one of the service gets stop, then other will be keep running in this case.
there are two types of dependencies (dep for short, from now on):
- requirement: implies tight coupling between (dependent) unit and dep. such that if dep fails to start, the unit will fail too. some of these are:
Requires=
Wants=
(weaker requirement coupling compared toRequires=
, wanted only for activating the unit,systemd
doesn't care if it fails)
- order: determines the order of units' start and stop. implements loose coupling (still a coupling!). does not prevent the current unit to start if dep fails to start. some of these are:
After=
Before=
- conditional: activate unit if a condition is met. this is a bit different than the above items since it's not explicitly a matter of units/services on both ends of the condition but here we are. some of these conditions are:
ConditionPathExists=cond
: activate unit ifcond
exists on the systemConditionFileNotEmpty=cond
: activate unit ifcond
is a file with a size of>=0
Roughly speaking, the former specifies which other units should be started (or stopped) when activating a unit, and the latter specifies in which order to start them. --source
As a supplement, mainly to Sebastián's answer:
"Note that requirement dependencies do not influence the order in which services are started or stopped."
One user above commented "What is a dependency if not a statement of order?", and I agree. I think that the statement is semi-correct. It should read:
"Note that requirement dependencies do not influence the exact order in which services are started or stopped."
Of course do dependencies influence the order:
If you got a bunch of seven services and one (and only one) of them depends on all the other services then you can predict that this service will be started later or at the same time as the other services.
If there's one service among the seven which doesn't have any dependencies but all the other services depend on it then you can predict that this service will be started earlier or at the same time as the other services.
Before=
and After=
exist to enable start order fine tuning for those services that would otherwise be started at the same time (or in random order).
What happens if service A depends on service B but service A shall start before service B?
systemd-analyze verify A.service
will tell you.
-
There is a huge difference between ordering and dependency. Ordering just means "if you are both in line, who goes first". Dependency means "if you want to start me, you must first start my dependency". Very, very different semantics.– AjaxCommented Jul 27 at 10:39