1

Suppose I have a.service which I cannot modify, and b.service which I can modify, I want to see this stop order:

Stopping b.service ...
Stopped b.service
Stopping a.service ...
Stopped a.service

instead of this:

Stopping b.service ...
Stopping a.service ...
Stopped b.service
Stopped a.service

Assume that b.service may take at least 20 seconds to finish.

filbranden
  • 21,113
  • 3
  • 58
  • 84
  • 1
    Related - https://serverfault.com/questions/785127/how-to-stop-systemd-services-in-specific-order. – slm Sep 03 '18 at 21:52

2 Answers2

3

In order to stop b.service before a.service, you need to actually order b.service after a.service, since the ordering at service stop time is the inverse of the order at start time.

So this should be enough to accomplish what you described:

# b.service unit file
[Unit]
Description=...
After=a.service

[Service]
...

See the documentation for After= in man systemd.unit, which states:

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.

You also asked about what happens if b.service takes at least 20 seconds to terminate. That is fine. If b.service is properly configured so systemd is able to monitor it until unit stop is completed (in other words, if ExecStop= is not somehow misconfigured) and if it stops before the timeout is reached (see TimeoutStopSec=), then systemd will wait until b.service is fully stopped before initializing shutdown of a.service.

filbranden
  • 21,113
  • 3
  • 58
  • 84
  • 2
    Oh I think I got confused because I saw `Stopped Qubes DB agent.`(as `a.service`) right after `Stopped Qubes Dom0 startup setup`(as `b.service`) and I assumed there should've been a `Stopping Qubes DB agent...` inbetween, but there wasn't because `Qubes DB agent` service is lacking any `ExecStop=` lines! So I thought the `Stopping` of `a.service` happened earlier than the `Stopped` for `b.service` which I took to mean that it didn't wait for `b.service` to fully stop before trying to stop `a.service`. But I was wrong. Thank you for your great answer! –  Sep 03 '18 at 21:54
  • Looks like it sometimes doesn't work, or there's something else happening. I tried 3 consecutive boots since I added `dev-block-253:0.device` to my `After=` in `qubes-core.service` (and did a `sudo systemctl daemon-reload` of course) and the 3rd boot acted as if I hadn't added that so the order wasn't respected! all details here: https://gist.github.com/constantoverride/61207ebf622263d25fb1e5b1f11d0148/9443ef0babe29b32622dd0f17a2435a9e0f1df92#gistcomment-2696607 (where `qubes-core.service` is just a page scroll above). I must be missing something, or is it a systemd bug? –  Sep 04 '18 at 01:52
0

If you merely want to stop these in a given order you can invoke the call to systemctl like this:

 $ systemctl stop a.service && systemctl stop b.service

or

 $ systemctl stop a.service; systemctl stop b.service
slm
  • 363,520
  • 117
  • 767
  • 871