I'm trying to get a service to run at :0/5:00 (every 5min) every time. This process may take more or less than 5min. If it passes the 5min mark, do nothing, and start the next one on the next 5min block.
This all works properly when the process takes less than 5min, but if the process takes more than 5min, it re-starts the service immediately.
From what I've read, the default behavior is to skip the next execution if the service time overflows (see https://unix.stackexchange.com/questions/203254/does-systemd-timer-unit-skip-the-next-run-if-the-process-hasnt-finished-yet). However, I also see a question which seems to indicate that the service will start as soon as the previous execution completes (see https://unix.stackexchange.com/questions/487562/how-to-make-systemd-timer-run-exactly-every-10-minutes-with-a-task-that-lasts-s) which fits with my expreiences.
(For testing purposes, I'm using :0/1:0 so that I don't have to wait 5min every time)
My timer:
[Unit]
Description=Start service on timed schedule.
After=network-online.target
Wants=network-online.target
[Timer]
OnCalendar=*:0/1:0
AccuracySec=1us
[Install]
WantedBy=timers.target
My service:
[Unit]
Description=Do a thing
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/bin/bash /usr/local/bin/my-script.sh
My script:
#!/bin/bash
PROG="/usr/local/bin/fake-third-party.sh"
exec $PROG &>> /tmp/timer_testing.out
Fake third-party script:
#!/bin/bash
echo "`date` I sleep now"
sleep 76
echo "`date` No more sleep"
So right now, when the 76s ends, it immediately starts the next one.
Thu Jun 25 13:01:00 UTC 2020 I sleep now
Thu Jun 25 13:02:16 UTC 2020 No more sleep
Thu Jun 25 13:02:16 UTC 2020 I sleep now
Thu Jun 25 13:03:32 UTC 2020 No more sleep
Thu Jun 25 13:03:32 UTC 2020 I sleep now
When what I'd be looking for is:
13:01:00 -> sleep
13:02:16 -> wake
13:03:00 -> sleep
13:04:16 -> wake
13:05:00 -> sleep
One possible (aka hacky) solution that is working right now is the following:
Change the my-script.sh
to have this at the front:
minutes=$(date +"%-M" | tail -c 2)
seconds=$(date +"%S")
if [[ "$seconds" != "00" || ! ( "$minutes" == "0" || "$minutes" == "5" ) ]]; then
then
exit 0
fi
This does trigger the my-script.sh
, but the script never calls exec third-party-script
so, it accomplishes the requirement.
However I would like to do this the 'proper' way, if there is one.