3

systemctl allows to pass multiple service names in start or stop command.

Let's assume in systemd service A is configured to be stopped before service B. When I now execute

systemctl stop B A

will then A and all dependent services be stopped first and then B even B is passed in the systemctl command first? I mean the sequence of service names in systemctl stop does not define the sequence the services are stopped.

I executed tests and they proved my assumption. But I want to be 100% sure it works all the time this way.

2

Not really! The current code is not so clever, it just tries to stop/start each service.

[It processes them in the order given. It is a little clever though. For some reason - presumably performance - it does not wait after each one, it only waits at the end. So it does not work like systemctl start A; systemctl start B. It is closer to systemctl start A & systemctl start B & wait.]

So if the unit files look like this -

# A.service
[Unit]
After=B.service

[Service]
Type=oneshot
ExecStart=/bin/sleep 2

# B.service
[Service]
Type=oneshot
ExecStart=/bin/sleep 2

systemctl start A B will start A and B. The current code does not guarantee to wait for B to be fully started before it starts A. [Currently A and B will start in parallel.] And you can see this in journalctl

Mar 20 20:50:29 alan-laptop systemd[2007]: Starting A.service...
Mar 20 20:50:29 alan-laptop systemd[2007]: Starting B.service...
Mar 20 20:50:31 alan-laptop systemd[2007]: Started A.service.
Mar 20 20:50:31 alan-laptop systemd[2007]: Started B.service. 

Whereas if A and B are pulled in to the initial transaction at boot time, they will be ordered as expected.

I thought it is possible to do something with systemd-run, to create and run a transient service, which either Requires / Wants or Conflicts with multiple other units. All their dependencies will be processed together. Then if unit A has an ordering dependency Before= or After= on unit B, that ordering dependency will be honoured.

  • Thank you very much for your answer @sourcejedi. But now I'm confused because your answer is contrary to the previous answer from filbranden – framp Mar 20 at 20:42
  • 1
    @framp The difference is I'm right :-P. Edited to show test output. – sourcejedi Mar 20 at 20:53
  • Looks like I did something wrong when I tested systemctl. Frankly I expected systemctl to use the dependencies between services when executing systemctl. Do you have any link which explains the rational why systemctl doesn't take into account the dependencies between services? – framp Mar 22 at 21:15
  • @framp just what I said - that the code doesn't do anything complex to make it so. I think the conclusion I reached v.s. the systemd-run approach, was that I didn't particularly want systemctl to start creating temporary units with random unique names in order to implement this. If you've got a cool example where it would be useful, maybe you could write it up somewhere. Upstream issue tracker asks you to test against current or previous upstream release first, if you want to send them a Request For Enhancement. – sourcejedi Mar 22 at 21:41
  • My initial comment is too long and I have to truncate it :-( I'm just working on a backup solution for Raspberries and wrote a script called raspiBackup. In particular I asked for systemctl behaviour to stop/start services before/after a backup. Systemd cares about all service dependencies during boot so I'm wondering why doesn't it care about these dependencies when multiple services are passed in systemctl. – framp Mar 22 at 22:34
1

Yes, your assumption is correct.

When you are starting or stopping multiple units in a single systemctl command, that will become a single transaction, so the system manager daemon (also known as PID 1) will attempt to start them all together.

If there are ordering dependencies (configured with Before= or After= directives), they will be considered at that point.

So if you have a configured ordering to start unit A after unit B (file A.service says After=B.service), which means unit A will be stopped before unit B (order is reversed when stopping units), then this will behave as you described: Units that depend on A will stop first (since they can't stay up when A is stopped), then A is stopped and then finally B is stopped.

If there are no ordering dependencies between the units, then they will be started or stopped in parallel. (What this means: systemd will still process them in sequence, but it will kill the process with a SIGTERM signal, or fork a process to execute the ExecStop= command for the unit, but it will not wait for the main PID to exit or for the ExecStop= command to complete, that's what "in parallel" means in this context. Since signals are asynchronous and forking is non-blocking, this is very close to true parallelism and for almost all effects can be considered the same.)

The order in which units are passed to the systemctl doesn't matter for most cases (only in very corner cases it will behave the same.) When there is an explicit ordering dependency, that will be respected. When there is not, the services will be started/stopped in parallel.

In short, systemctl stop B A and systemctl stop A B are essentially the same.

  • Thank you very much for your answer @filbranden. But now I'm confused because your answer is contrary to the following answer from sourcejedi – framp Mar 20 at 20:43
  • Looks like @sourcejedi is correct. I answered based on my conceptual understanding of how I thought this was supposed to work. Go by his answer. – filbranden Mar 20 at 22:54
  • Frankly this was also my understanding. Would be great to know why systemctl doesn't work this way. – framp Mar 22 at 21:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.