[systemd-devel] Waiting for all jobs to finish

Barry Scott barry at barrys-emacs.org
Thu Apr 28 10:09:40 UTC 2022



> On 28 Apr 2022, at 09:47, Lennart Poettering <lennart at poettering.net> wrote:
> 
> On Mi, 27.04.22 18:29, Barry Scott (barry at barrys-emacs.org <mailto:barry at barrys-emacs.org>) wrote:
> 
>> I have two target files that I use.
>> 
>> prod.target is used to start up all the production services.
>> When I use systemctl start prod.target it blocks until all the
>> services are running.
>> 
>> I also have prod-upgrade.target that is used to stop service
>> via Conflicts=. When I use systemctl start prod-upgrade.target
>> it returns immediately but there are stop jobs running.
>> 
>> I believe that this is expected as all the services that need to
>> be started have been.
>> 
>> Is there a systemctl command that will wait for all the stop jobs
>> without the need to poll for the systemctl list-jobs to be empty?
> 
> There is not.
> 
> But the correct way to solve this is by combining Conflicts= with an
> order dep (After= or Before=).
> 
> In systemd the ordering deps After=/Before= control three things:
> 
> 1. The literally define the start-up order if two units are started,
> i.e. this is the obvious case: if b.service has After=a.service
> this means a.service has to finish startup first, before b.service
> is started.
> 
> 2. If two units are stopped they define the order too, but in
> reverse. if b.service has After=a.service this hence means that if
> both are shutdown, then b.service has to stop *before* a.service is
> stopped, i.e. the opposite order of the start-up order.
> 
> 3. If one unit is started and one is stopped then the existance of an
> ordering dep means the stopped unit must complete stopping first,
> before the starting of the other is initiated. Note that it doesn't
> mattre if you set After= or Before= here, that doesn#t matter. What
> matters is that you ordered the unit at all, regardless in which
> direction.
> 
> Now, this third rule is what matters here: if your target unit has
> Conflicst= on some service, then the target unit should not enter
> active state until the service fully shutdown. Thus you can place
> After= *or* Before= between the two (your choice) and get the desired
> behaviour.

I'd have never reasoned my way to this solution.

It work as you described.

But only if I use After= as Before= got a cyclic deps error.

Here is the pattern I now have:

[Unit]
Description=prod.target

Wants=serv1.service
After=serv1.service


[Unit]
Description=prod-upgrade.target

Conflicts=prod.target
Conflicts=serv1.service

# Need a After= so that systemctl start prod-upgrade.target
# will block until conflicting services have stopped
After=serv1.service

Barry


> 
> Lennart
> 
> --
> Lennart Poettering, Berlin

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/systemd-devel/attachments/20220428/b8ba9dc2/attachment-0001.htm>


More information about the systemd-devel mailing list