Re: [systemd-devel] Mutually exclusive (timer-triggered) services

2019-10-31 Thread Lennart Poettering
On Mo, 14.10.19 18:30, Alexander Koch (m...@alexanderkoch.net) wrote:

> * flock leaves the lock file behind so you'd need some type of cleanup in
> case
>   you really want the jobs to be trace-free. This is not as trivial as it
> might
>   seem, e.g. you cannot do it from the service units themselves in
>   `ExecStartPost=` or similar.

Linux supports BSD and POSIX locks on all kinds of fs objects,
including dirs. It should be possible to just lock the cache dir or so
of pacman (i.e. an fs object that exists anyway), no need to introduce
a new locking file.

Lennart

--
Lennart Poettering, Berlin
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel

Re: [systemd-devel] Mutually exclusive (timer-triggered) services

2019-10-31 Thread Lennart Poettering
On Mo, 14.10.19 12:45, Alexander Koch (m...@alexanderkoch.net) wrote:

> Dear [systemd-devel],
>
> imagine you've got multiple services that perform system housekeeping
> tasks, all triggered by .timer units. These services all happen to use
> a specific resource (e.g. the system package manager) so they must not
> be run in parallel, but they all need to be run.
>
> Is there a systemd'ish way of modeling this?
>
> I first thought of using `Conflicts=` but having read the manpages I
> understand that queueing one of the services would actively stop any
> running instance of any of the others.
>
> `After=` is not an option either as that (unless 'Type=oneshot', which
> isn't to be used for long-running tasks) doesn't delay up to completion
> but only to initialization. Furthermore I think you'd run into trouble
> ordering more than two units using this approach.
>
> Ideally I'd think of something like a 'virtual resource' that can be
> specified by service units, like this (real use case on Arch Linux):
>
> [Unit]
> Description=Pacman sync
> Locks=pacman-db
>
> [Service]
> ExecStart=/usr/bin/pacman -Sy
>
> 
>
> [Unit]
> Description=Pacman cleanup
> Locks=pacman-db
>
> [Service]
> ExecStart=/usr/bin/paccache -r -k 0 -u
>
> The value of `Locks=` shall be an arbitrary string describing the
> virtual resource the service is requiring exclusive access to. systemd
> would then delay the start of a unit if there is another unit with
> identical `Locks=` entry currently active.
>
> A nice advantage of this concept is that services depending on the same
> virtual resource would not need to know of each other, which simplifies
> shipping them via separate packages.
>
> Any thoughts on this? Maybe I'm just too blind to see the obvious
> solution to this simple problem.

I presume pacman uses file system locks anyway, no? I think the best
approach would be to make those (optionally) blocking directly in
pacman, no?

I mean, you can add five layers of locking on top, but ultimately it
appears to me in this case you just want to make the locking that
already exists just blocking. Linux fs locking exists in non-blocking
*and* blocking flavour anyway, it's just a matter of making pacman
expose that, maybe with a new --block switch or so?

Other than that you can of course use tools such as "flock(1)" around
pacman.

Lennart

--
Lennart Poettering, Berlin
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel

Re: [systemd-devel] Mutually exclusive (timer-triggered) services

2019-10-15 Thread Alexander Koch

* flock leaves the lock file behind so you'd need some type of
cleanup in case you really want the jobs to be trace-free. This is
not as trivial is it might seem, e.g. you cannot do it from the
service units themselves in `ExecStartPost=` or similar.

An

ExecStartPost=-/usr/bin/flock -F /path/to/lock.file \
  /usr/bin/rm /path/to/lock.file

should solve this issue.


So you can remove a file other processes are blocked lock-waiting on? 
Didn't

expect this to work, thanks for the hint.


If your units are actually dependent on each other, than maybe you
should think about your approach in general. But to be able to help you
with that we need more information about the actual dependencies of the
applications started by your units and at which interval they shall
run.


Okay I guess I should come up with the actual scenario, here we go:

On my Arch Linux workstation I've got three .timer triggered .service 
units
that do package manager housekeeping (I don't know if you're familiar 
with

Arch/Pacman so I'll annotate their purposes):

1) Synchronize package database (equivalent of `apt-get update` on 
Debian)


[Timer]
OnCalendar=8-17/2:00
Persistent=true

[Service]
ExecStart=/usr/bin/pacman -Syq

2) Update file database (equivalent of `apt-file update`)

[Timer]
OnCalendar=weekly
Persistent=true

[Service]
ExecStart=/usr/bin/pacman -Fyq

3) Purge old packages from cache (something like `apt-get autoclean`)

[Timer]
OnCalendar=daily
Persistent=true

[Service]
ExecStart=/bin/sh -c 'paccache -r -k 2; paccache -r -k 0 -u'

As you can see, I'd like to have different execution intervals for all 
of
these tasks so I'd like to keep them as separate services (which also 
seems

the intuitive approach to me).

I must admit that I haven't tried, but I'm pretty sure that at least 1 
and
2 do lock the ALPM database so if you try to issue one of these Pacman 
calls
while the other is running it will fail, complaining about a lock file 
being

present.

My current workaround for this is using `RandomizedDelaySec=15m` in
conjunction with `AccuracySec=1` in the .timer units to spread the 
triggers.


While this does work I'm really curious about the 'proper' way of 
modeling
this. Is it such an academic problem to have the need of ensuring that 
two

timers (or services) don't fire simultaneously? I had thought this to be
really simple with such an elaborate service manager like systemd, with 
all

its graph theory power and the-like.

(If I were a heretic I'd say 'We can do DNS, DHCP and NTP with systemd
without any third party software but we need additional utilities to 
ensure

that two things don't happen at the same time??' ;) )

I think there are plenty of other scenarios, e.g. ideally I'd like my 
backup
service not to kick in while btrfs-scrub@home.service is running... or 
maybe

it's just me seeing this need ;)


Best regards,

Alex
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel

Re: [systemd-devel] Mutually exclusive (timer-triggered) services

2019-10-15 Thread Silvio Knizek
Am Montag, den 14.10.2019, 18:30 +0200 schrieb Alexander Koch:
> > exactly for this you would use a flock(1) in your .service.
>
> Thanks for the hint, didn't have that in mind. So you're suggesting
> something like this?
>
>  # service-a.service
>  # (...)
>  [Service]
>  ExecStart=/usr/bin/flock -F /var/lock/resource.lock
> /usr/bin/service-a
>
>  # service-b.service
>  # (...)
>  [Service]
>  ExecStart=/usr/bin/flock -F /var/lock/resource.lock
> /usr/bin/service-b
>
>
> I see some drawbacks of this approach:
>
> * Wrapping the actual command in an flock call seems pretty ugly in
> my eyes, i.e. looking at the `ExecStart=` lines above I find it very
> hard to see where the former begins, at first glance. This is
> subjective, of course.
You could use something like

ExecStart=/usr/bin/flock -F /path/to/lock.file \
  /your/actual/command --with argument

Should be easier on the eyes.
>
> * flock leaves the lock file behind so you'd need some type of
> cleanup in case you really want the jobs to be trace-free. This is
> not as trivial is it might seem, e.g. you cannot do it from the
> service units themselves in `ExecStartPost=` or similar.
An

ExecStartPost=-/usr/bin/flock -F /path/to/lock.file \
  /usr/bin/rm /path/to/lock.file

should solve this issue.
>
> * /var/lock is very likely not user-writable so you'd need a
> different lock file directory for user services. You could of course
> use /tmp for that.
For this I would suggest StateDirectory=. See man:systemd.exec for more
information
>
> * File-based locking makes it impossible to use private filesystem
> namespaces for the service units (think of `PrivateTmp=yes` and lock
> files in /tmp).
If a StateDirectory= is used than only the access rights are important.
>
>
> As systemd (or service managers in general) are all about queueing,
> ordering and controlling services and their dependencies I had hoped
> there would be a cleaner solution using systemd internals rather than
> solving it using external tools, which mixes up the service call
> itself with its requirements (exclusive resource access).
>
> Nevertheless I think I will go with your proposal and see how it
> works out.
If your units are actually dependent on each other, than maybe you
should think about your approach in general. But to be able to help you
with that we need more information about the actual dependencies of the
applications started by your units and at which interval they shall
run.
>
>
> Best regards,
>
> Alex
BR
Silvio

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel

Re: [systemd-devel] Mutually exclusive (timer-triggered) services

2019-10-14 Thread Alexander Koch

exactly for this you would use a flock(1) in your .service.


Thanks for the hint, didn't have that in mind. So you're suggesting 
something

like this?

# service-a.service
# (...)
[Service]
ExecStart=/usr/bin/flock -F /var/lock/resource.lock 
/usr/bin/service-a


# service-b.service
# (...)
[Service]
ExecStart=/usr/bin/flock -F /var/lock/resource.lock 
/usr/bin/service-b



I see some drawbacks of this approach:

* Wrapping the actual command in an flock call seems pretty ugly in my 
eyes,
  i.e. looking at the `ExecStart=` lines above I find it very hard to 
see where

  the former begins, at first glance. This is subjective, of course.

* flock leaves the lock file behind so you'd need some type of cleanup 
in case
  you really want the jobs to be trace-free. This is not as trivial as 
it might

  seem, e.g. you cannot do it from the service units themselves in
  `ExecStartPost=` or similar.

* /var/lock is very likely not user-writable so you'd need a different 
lock file

  directory for user services. You could of course use /tmp for that.

* File-based locking makes it impossible to use private filesystem 
namespaces
  for the service units (think of `PrivateTmp=yes` and lock files in 
/tmp).



As systemd (or service managers in general) are all about queueing, 
ordering and
controlling services and their dependencies I had hoped there would be a 
cleaner
solution using systemd internals rather than solving it using external 
tools,
which mixes up the service call itself with its requirements (exclusive 
resource

access).

Nevertheless I think I will go with your proposal and see how it works 
out.



Best regards,

Alex
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel

Re: [systemd-devel] Mutually exclusive (timer-triggered) services

2019-10-14 Thread Silvio Knizek
Am Montag, den 14.10.2019, 12:45 +0200 schrieb Alexander Koch:
> Dear [systemd-devel],
>
> imagine you've got multiple services that perform system housekeeping
> tasks, all triggered by .timer units. These services all happen to
> use
> a specific resource (e.g. the system package manager) so they must
> not
> be run in parallel, but they all need to be run.
>
> Is there a systemd'ish way of modeling this?
>
> I first thought of using `Conflicts=` but having read the manpages I
> understand that queueing one of the services would actively stop any
> running instance of any of the others.
>
> `After=` is not an option either as that (unless 'Type=oneshot',
> which
> isn't to be used for long-running tasks) doesn't delay up to
> completion
> but only to initialization. Furthermore I think you'd run into
> trouble
> ordering more than two units using this approach.
>
> Ideally I'd think of something like a 'virtual resource' that can be
> specified by service units, like this (real use case on Arch Linux):
>
>  [Unit]
>  Description=Pacman sync
>  Locks=pacman-db
>
>  [Service]
>  ExecStart=/usr/bin/pacman -Sy
>
>  
>
>  [Unit]
>  Description=Pacman cleanup
>  Locks=pacman-db
>
>  [Service]
>  ExecStart=/usr/bin/paccache -r -k 0 -u
>
> The value of `Locks=` shall be an arbitrary string describing the
> virtual resource the service is requiring exclusive access to.
> systemd
> would then delay the start of a unit if there is another unit with
> identical `Locks=` entry currently active.
>
> A nice advantage of this concept is that services depending on the
> same
> virtual resource would not need to know of each other, which
> simplifies
> shipping them via separate packages.
>
> Any thoughts on this? Maybe I'm just too blind to see the obvious
> solution to this simple problem.
>
>
> Best regards,
>
> Alex
Hi Alex,

exactly for this you would use a flock(1) in your .service.

BR
Silvio

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel

[systemd-devel] Mutually exclusive (timer-triggered) services

2019-10-14 Thread Alexander Koch

Dear [systemd-devel],

imagine you've got multiple services that perform system housekeeping
tasks, all triggered by .timer units. These services all happen to use
a specific resource (e.g. the system package manager) so they must not
be run in parallel, but they all need to be run.

Is there a systemd'ish way of modeling this?

I first thought of using `Conflicts=` but having read the manpages I
understand that queueing one of the services would actively stop any
running instance of any of the others.

`After=` is not an option either as that (unless 'Type=oneshot', which
isn't to be used for long-running tasks) doesn't delay up to completion
but only to initialization. Furthermore I think you'd run into trouble
ordering more than two units using this approach.

Ideally I'd think of something like a 'virtual resource' that can be
specified by service units, like this (real use case on Arch Linux):

[Unit]
Description=Pacman sync
Locks=pacman-db

[Service]
ExecStart=/usr/bin/pacman -Sy



[Unit]
Description=Pacman cleanup
Locks=pacman-db

[Service]
ExecStart=/usr/bin/paccache -r -k 0 -u

The value of `Locks=` shall be an arbitrary string describing the
virtual resource the service is requiring exclusive access to. systemd
would then delay the start of a unit if there is another unit with
identical `Locks=` entry currently active.

A nice advantage of this concept is that services depending on the same
virtual resource would not need to know of each other, which simplifies
shipping them via separate packages.

Any thoughts on this? Maybe I'm just too blind to see the obvious
solution to this simple problem.


Best regards,

Alex
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel