仅在日历事件上使用 systemd 定时器
Only use systemd timer oncalendar events
我正在尝试在 :0/5:00(每 5 分钟)获取到 运行 的服务。此过程可能需要 5 分钟或多于或少于 5 分钟。如果它超过了 5 分钟标记,则什么也不做,并在下一个 5 分钟块开始下一个。
当该过程花费的时间少于 5 分钟时,这一切都正常工作,但如果该过程花费的时间超过 5 分钟,它会立即重新启动服务。
根据我的阅读,默认行为是在服务时间溢出时跳过下一次执行(参见 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),这符合我的经验。
(出于测试目的,我使用 :0/1:0 这样我就不必每次都等待 5 分钟)
我的计时器:
[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
我的服务:
[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
我的脚本:
#!/bin/bash
PROG="/usr/local/bin/fake-third-party.sh"
exec $PROG &>> /tmp/timer_testing.out
伪造的第三方脚本:
#!/bin/bash
echo "`date` I sleep now"
sleep 76
echo "`date` No more sleep"
所以现在,当 76 结束时,它会立即开始下一个。
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
当我要寻找的是:
13:01:00 -> sleep
13:02:16 -> wake
13:03:00 -> sleep
13:04:16 -> wake
13:05:00 -> sleep
目前正在使用的一种可能(又名骇人听闻的)解决方案如下:
更改 my-script.sh
使其位于前面:
minutes=$(date +"%-M" | tail -c 2)
seconds=$(date +"%S")
if [[ "$seconds" != "00" || ! ( "$minutes" == "0" || "$minutes" == "5" ) ]]; then
then
exit 0
fi
这确实触发了 my-script.sh
,但脚本从未调用 exec third-party-script
,因此它满足了要求。
不过我想用 'proper' 的方式来做,如果有的话。
我正在尝试在 :0/5:00(每 5 分钟)获取到 运行 的服务。此过程可能需要 5 分钟或多于或少于 5 分钟。如果它超过了 5 分钟标记,则什么也不做,并在下一个 5 分钟块开始下一个。
当该过程花费的时间少于 5 分钟时,这一切都正常工作,但如果该过程花费的时间超过 5 分钟,它会立即重新启动服务。
根据我的阅读,默认行为是在服务时间溢出时跳过下一次执行(参见 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),这符合我的经验。
(出于测试目的,我使用 :0/1:0 这样我就不必每次都等待 5 分钟)
我的计时器:
[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
我的服务:
[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
我的脚本:
#!/bin/bash
PROG="/usr/local/bin/fake-third-party.sh"
exec $PROG &>> /tmp/timer_testing.out
伪造的第三方脚本:
#!/bin/bash
echo "`date` I sleep now"
sleep 76
echo "`date` No more sleep"
所以现在,当 76 结束时,它会立即开始下一个。
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
当我要寻找的是:
13:01:00 -> sleep
13:02:16 -> wake
13:03:00 -> sleep
13:04:16 -> wake
13:05:00 -> sleep
目前正在使用的一种可能(又名骇人听闻的)解决方案如下:
更改 my-script.sh
使其位于前面:
minutes=$(date +"%-M" | tail -c 2)
seconds=$(date +"%S")
if [[ "$seconds" != "00" || ! ( "$minutes" == "0" || "$minutes" == "5" ) ]]; then
then
exit 0
fi
这确实触发了 my-script.sh
,但脚本从未调用 exec third-party-script
,因此它满足了要求。
不过我想用 'proper' 的方式来做,如果有的话。