139

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 6

112

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.

4
  • 25
    What is a dependency if not a statement of order? (seriously... I don't understand the difference)
    – TomOnTime
    Commented Nov 1, 2016 at 20:29
  • 7
    See my edit. My understanding: After=X would mean "Do this after X if X is done", while Require=X would mean "don't do this at all if you can't do X".
    – Sven
    Commented Nov 1, 2016 at 20:32
  • 2
    The 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 if bar.service isn't started anyway and foo.service would start normally.
    – Sven
    Commented 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
50

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 if network-online.target.
  • if network-online.target not started, it will wait.
  • test-app starts only after network-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 and test-app are activated together
  • if network-online.target fails to start test-app will not be activated.
2
  • 2
    You say After “does not explicitly activate the specified units.” Does that mean that with After and no Wants or Requires, the dependency may never start, and thus our service may never start?
    – Jacktose
    Commented Nov 6, 2021 at 1:16
  • 1
    @Jacktose yes .
    – Étienne
    Commented Jun 13, 2023 at 11:30
14

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).

2
  • 3
    It sounds like After implies Requires. Can I use After alone, with out Requires/Wants?
    – Jacktose
    Commented Nov 6, 2021 at 1:17
  • 1
    @Jacktose If you do that, and you start the service with an After, and the service IN the After isn't already started, it will not be automatically started. For that you'll need Requires or Wants, which is precisely why these two options are often used together.
    – Arad
    Commented Nov 18, 2022 at 20:37
2

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.
1

there are two types of dependencies (dep for short, from now on):

  1. 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 to Requires=, wanted only for activating the unit, systemd doesn't care if it fails)
  2. 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=
  3. 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 if cond exists on the system
    • ConditionFileNotEmpty=cond: activate unit if cond 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

0

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.

1
  • 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.
    – Ajax
    Commented Jul 27 at 10:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .