[systemd-devel] systemd.timer every X days?

Lennart Poettering lennart at poettering.net
Tue Jul 28 14:08:29 UTC 2020


On So, 26.07.20 14:56, Ian Pilcher (arequipeno at gmail.com) wrote:

> My NAS has 16 MD RAID devices.  I've created a simple service
> (raidcheck at .service) that will trigger a check of the RAID device
> identified by the argument.  E.g., 'systemctl start raidcheck at md1' will
> trigger the check of md1 (after checking that no other array is being
> checked/synced, no arrays are degraded, etc.).
>
> It takes 6-8 hours to check one of these arrays, so I want to run one
> check every night at 23:00.  So (picking tonight as an arbitrary
> starting point) md1 would run tonight, md2 would run tomorrow night, md3
> would run the following night ... all the way through md16.  Then the
> cycle would start over with md1.
>
> I had thought that I would be able to create 16 separate timers (one for
> each device), each scheduled to trigger every 16 days at 23:00, starting
> on a particular day.
>
> Looking through the systemd.timer(5) and systemd.time(7) man pages,
> however, I haven't been able to figure out how to do this.  Is it not
> possible, or am I missing something?

So what you are trying to do here is a mixture of calendar based
scheduling and monotonic scheduling. You could schedule the first
iteration via OnCalendar= and then schedule subsequent iterations via
OnUnitActiveSec=, but it's sloppy, since first of all this will
accumulate the latency of activation, and then as soon as you have a
DST change things will go completely off.

We might be able to extend our calendar language natively to support
something like this, i.e. calendar expressions that use monotonic
adjusted repetition values, but quite frankly I don't even know how
such an expression language could look like.

Maybe a workable way is to just enqueue a transient timer for the next
iteration at the end (or beginning) of your service, i.e. use
systemd-timer with some minimal shell scripting. i.e.

systemd-run --on-calendar=`date --date=@$((\`date -u +%s\` + 16*24*60*60+12*60*60)) %d-%m-%y 23:00:00` …

(totally untested, but you get the idea: add 16.5 days to the current
unix day, then break that down to the day, and use that to re-enqueue
a transient calendar event)

Lennart

--
Lennart Poettering, Berlin


More information about the systemd-devel mailing list