Re: [systemd-devel] Mutually exclusive (timer-triggered) services
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
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
* 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
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
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
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
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