1

I can't wrap my head around systemd unit files.

Here's my scenario, I have a service called: my.service

my.service needs to start sometime after boot, whenever everything else is ready, no rush.

my.service starts a docker container so I want to start the docker.service before starting my.service (it is possible that docker.service is disable on my system).

Whenever the docker.service and/OR when management.service are restarted, I'd like my.service to be restarted as well (after docker and management).

my.service needs to be started after management.service

Now i'm so confused between Requires=, After=, Wants= BindsTo= ReloadPropagatedFrom= etc... I've been using on combination of those but it doesn't seem to start docker.service nor my.service

[Unit]
Description=test
Requires=management.service
After=multi-user.target
Wants=docker.service management.service multi-user.target
BindsTo=docker.service management.service
ReloadPropagatedFrom=docker.service

[Service]
ExecStartPre=/usr/bin/start.sh
ExecStop=/usr/bin/stop.sh
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target

what am I doing wrong?

3
  • Does my.service need to be started after management.service as well?
    – Natolio
    Jan 12, 2022 at 18:45
  • @Natolio yes it does, i forgot to add this to my post!
    – Tuono
    Jan 12, 2022 at 19:37
  • Go ahead and update your question to reflect this. I'll update my answer to do so as well.
    – Natolio
    Jan 12, 2022 at 19:42

1 Answer 1

0

Check out the systemd.unit man page to see descriptions, I've included them below, but will do my best to explain.

Requires is a strong dependency. If my.service gets activated then anything listed after Requires= also gets activated. If one of the units listed after Requires= is explicitly stopped, then my.service also is stopped. If there are no Before= or After= used to set ordering for my.service and a unit listed after Requires= then they will be started simultaneously.

Wants is a weaker dependency. Units listed after Wants= will be started if my.service is started. However if a listed unit has issues starting then it does not stop my.service from starting.

BindsTo is an even stronger dependency than Requires. It is like requires, but if for any reason a service that is listed after BindsTo= stops for any reason then my.service will also be stopped.

After and Before are both used to specify an order. They are independent settings from Requires, Wants, and BindsTo, but can be used alongside them to specify the order in which the services should be started.

PropagatesReloadTo and PropagatesReloadFrom are used to queue up reloads across multiple units. If my.service specified PropagatesReloadTo=docker.service then reloading my.service would also reload docker.service. If my.service specified PropagatesReloadFrom=docker.service then reloading docker.service would also reload my.service.

It is more or less recommended to use Wants when possible over using Requires or BindsTo.

Do not overlap services with Wants, Requires, and BindsTo. Decide which fits the need for your service for the unit files you want to specify and go with it.

Whenever the docker.service and/OR when management.service are restarted, I'd like my.service to be restarted as well (after docker and management).

If you would like to restart a service if another service is restarted then you can use PartOf= instead of Requires.

PartOf= Configures dependencies similar to Requires=, 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.

my.service starts a docker container so I want to start the docker.service before starting my.service (it is possible that docker.service is disable on my system).

After=docker.service management.service to set my.service to start after docker.service and management.service Since you would like the restart as listed above use PartOf=docker.service management.service. If you did not need the restart to be propagated, then you would likely decide between Wants, Requires, and BindsTo. Try to not create unnecessary strong dependencies though.

Then

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 fails to activate, and an ordering dependency After= on the 
    failing unit is set, this unit will not be started. Besides, with or without specifying After=, this unit will be stopped if one of the other units is explicitly stopped. 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.

    Note that this dependency type does not imply that the other unit always has to be in active state when this unit is running. Specifically: failing condition checks (such as ConditionPathExists=,
    ConditionPathIsSymbolicLink=, ... — see below) do not cause the start job of a unit with a Requires= dependency on it to fail. Also, some unit types may deactivate on their own (for example, a service process may decide 
    to exit cleanly, or a device may be unplugged by the user), which is not propagated to units having a Requires= dependency. Use the BindsTo= dependency type together with After= to ensure that a unit may never be in
    active state without a specific other unit also in active state (see below).
Wants= 
    A weaker version of Requires=. Units listed in this option will be started if the configuring unit is. However, if the listed units fail to start or cannot be added to the transaction, this has no impact on the validity
    of the transaction as a whole. This is the recommended way to hook start-up of one unit to the start-up of another unit.
Before=, After= 
    These two settings expect a space-separated list of unit names. They configure 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 has finished starting up. Note that this setting is independent of and orthogonal to the requirement dependencies as configured by Requires=, Wants= or BindsTo=. It is
    a common pattern to include a unit name in both the After= and Requires= options, 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, 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=, in this case. 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. It depends on the unit type when precisely a unit has finished starting up. Most importantly, for service units start-up is considered completed for the purpose of
    Before=/After= when all its configured start-up commands have been invoked and they either failed or reported start-up success.
BindsTo=
    Configures requirement dependencies, very similar in style to Requires=. However, this dependency type is stronger: in addition to the effect of Requires= it declares that if the unit bound to is stopped, this unit will
    be stopped too. This means a unit bound to another unit that suddenly enters inactive state will be stopped too. Units can suddenly, unexpectedly enter inactive state for different reasons: the main process of a service
    unit might terminate on its own choice, the backing device of a device unit might be unplugged or the mount point of a mount unit might be unmounted without involvement of the system and service manager.

    When used in conjunction with After= on the same unit the behaviour of BindsTo= is even stronger. In this case, the unit bound to strictly has to be in active state for this unit to also be in active state. This not
    only means a unit bound to another unit that suddenly enters inactive state, but also one that is bound to another unit that gets skipped due to a failed condition check (such as ConditionPathExists=,
    ConditionPathIsSymbolicLink=, ... — see below) will be stopped, should it be running. Hence, in many cases it is best to combine BindsTo= with After=.
PropagatesReloadTo=, ReloadPropagatedFrom=
    A space-separated list of one or more units where reload requests on this unit will be propagated to, or reload requests on the other unit will be propagated to this unit, respectively. Issuing a reload request on a
    unit will automatically also enqueue a reload request on all units that the reload request shall be propagated to via these two settings.
7
  • Thanks for your answer! I haven't had the time to try that yet, hopefully this weekend or early next week, I will let you know! :)
    – Tuono
    Jan 14, 2022 at 16:38
  • No problem, leave a comment if you run into problems and I'll see if I can help sort it out.
    – Natolio
    Jan 14, 2022 at 16:53
  • For some reasons the boot case wouldn't work when I try to set the dependency on both docker.service and management.service [Unit] Description=Test Requires=management.service After=management.service [Install] WantedBy=multi-user.target
    – Tuono
    Jan 28, 2022 at 2:29
  • If I add "docker.sevice" to the Requires= and After= entry it works fine when I stop/reload both docker.service and management.service, but I try to reboot, my.service wouldn't start. I'm not even sure why. ``` $ systemctl status my.service ● my.service - Test3 Loaded: loaded (/etc/systemd/system/my.service; enabled; vendor preset: enabled) Active: inactive (dead)```
    – Tuono
    Jan 28, 2022 at 2:32
  • 1
    @Natolio there is an important typo which changes the meaning of your answer: "However if a listed unit has issues starting then it does stop my.service from starting." The correct sentence is "it does NOT stop my.service from starting"
    – Étienne
    Feb 6 at 9:51

You must log in to answer this question.

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