[systemd-devel] Services with multiple pre-requisites

Andrei Borzenkov arvidjaar at gmail.com
Mon Dec 21 18:18:04 UTC 2020


21.12.2020 20:23, freedesktop at priatel.co.uk пишет:
> Perhaps I'm missing something, but that's still not doing what I expect.
> 
> Here's what I have...
> 
> #----- /etc/systemd/system/first.target -----#
> [Unit]
> Description=Started first
> Wants=third.service
> 
> #----- /etc/systemd/system/second.target -----#
> [Unit]
> Description=Started second
> Wants=third.service
> 
> #----- /etc/systemd/system/third.service -----#
> [Unit]
> Description=Third service
> Requisite=first.target second.target
> 
> [Service]
> Type=simple
> ExecStartPre=/usr/bin/logger -t "FooBar" -p daemon.notice "%P is starting"
> ExecStart=/tmp/third.sh
> Restart=always
> ExecStop=/usr/bin/logger -t "FooBar" -p daemon.notice "%P has stopped"
> 
> 
> #----- /tmp/third.sh -----#
> #!/bin/bash
> count=1
> while (( count > 0 ))
> do
>   /usr/bin/logger -i -t "FooBar" -p daemon.notice "Counter: $count"
>   (( count++ ))
>   sleep 5
> done
> 
> And here's what I observe happening. When I start *either* first.target or
> second.target, the third.service is started. That's not what I expect or
> want though. The third.service should be requisite on **both** first.target
> and second.target.
> 
> localhost# systemctl start first.target
> 
> 2020-12-21T17:03:51.039814+00:00 localhost systemd[1]: Starting Third
> service...
> 2020-12-21T17:03:51.041827+00:00 localhost FooBar: Third service is starting
> 2020-12-21T17:03:51.042451+00:00 localhost systemd[1]: Started third
> service.
> 2020-12-21T17:03:51.045033+00:00 localhost systemd[1]: Reached target
> Started first.
> 2020-12-21T17:03:51.045114+00:00 localhost systemd[1]: Started second is not
> active.
> 2020-12-21T17:03:51.045843+00:00 localhost FooBar[29048]: Counter: 1
> 2020-12-21T17:03:56.048463+00:00 localhost FooBar[644]: Counter: 2
> 2020-12-21T17:04:01.050951+00:00 localhost FooBar[4881]: Counter: 3
> 
> localhost# systemctl stop first.target
> ...
> localhost# systemctl start second.target
> 
> 2020-12-21T17:04:47.544840+00:00 localhost systemd[1]: Starting Third
> service...
> 2020-12-21T17:04:47.546885+00:00 localhost FooBar: Third Service is starting
> 2020-12-21T17:04:47.555459+00:00 localhost systemd[1]: Started third
> service.
> 2020-12-21T17:04:47.555556+00:00 localhost FooBar[3938]: Counter: 1
> 2020-12-21T17:04:47.555666+00:00 localhost systemd[1]: Started first is not
> active.
> 2020-12-21T17:04:47.555730+00:00 localhost systemd[1]: Reached target
> Started second.
> 2020-12-21T17:04:52.553867+00:00 localhost FooBar[8255]: Counter: 2
> 2020-12-21T17:04:57.554741+00:00 localhost FooBar[12157]: Counter: 3
> 
> localhost# systemctl stop second.target
> 
> Note particularly the `systemd` logs:
> 
> 2020-12-21T17:03:51.045114+00:00 localhost systemd[1]: Started second is not
> active.
> 2020-12-21T17:04:47.555666+00:00 localhost systemd[1]: Started first is not
> active.
> 
> It has noticed and logged that one of the Requisite targets for the Third
> service isn't active, but it starts it anyway :-(
> 
> That seems to go directly against the documented behaviour (at
> https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Requisite
> =):
>   | Requisite=
>   | 
>   |     Similar to Requires=. However, if the units listed here are not
>   |     started already, they will not be started and the starting of
>   |     this unit will fail immediately.
> 
> Is this a bug, or am I still missing something?
> 

You miss ordering dependencies. Neither Requires not Requisite work
without proper After/Before.

systemd manuals make impression that dependencies are between units.
This is wrong - dependencies are between jobs. If unit B has "Requisite:
A" what happens is - systemd implicitly creates job for unit A that
verifies current state of unit A and if it is not active fails pending
start job for unit B. Without proper ordering both jobs (verify state of
unit A and start unit B) run concurrently and the order is
non-deterministic (or may be it is but then it is always "wrong" for
your purpose :) ), so in your case job for Second runs too late, when
Third is already started and there is no pending job to fail.



> Martin
> 
> -----Original Message-----
> From: Lennart Poettering <lennart at poettering.net> 
> Sent: 21 December 2020 15:32
> To: freedesktop at priatel.co.uk
> Cc: systemd-devel at lists.freedesktop.org
> Subject: Re: [systemd-devel] Services with multiple pre-requisites
> 
> On Mo, 21.12.20 14:43, freedesktop at priatel.co.uk (freedesktop at priatel.co.uk)
> wrote:
> 
>> Hi
>>
>> I have two "primary" services running on a Linux server with `systemd` 
>> that may be started at approximately the same time, or could just as 
>> easily be started days apart. When started, they take a few seconds to
> reach "ready"
>> state, and can signal that readiness however I choose.
>>
>> I have a third (and fourth, fifth, etc...) service which:
>>   * must not start before both Service 1 & Service 2 are ready
>>   * must start as soon as possible once both Service 1 & Service 2 are
> ready
>>   * must be stopped as soon as possible if either Service 1 or Service 
>> 2 terminates
> 
> Did I get this right: service 3 is not supposed to pull in services 1
> + 2, but just be activated as side-effect of those services being
> activated? i.e. the activation of service 1 and 2 need to happen first and
> they are the trigger for service 3, but besides that noone ever asks for
> service 3?
> 
> If so, it appears to me a Wants= dep from services 1 and 2 on 3 would make
> sense, plus a Requisite= dep in the other direction.
> 
> Lennart
> 
> --
> Lennart Poettering, Berlin
> 
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/systemd-devel
> 



More information about the systemd-devel mailing list