[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