您在 minutes 说明符中有 */30 - 这意味着每分钟但步长为 30(换句话说,每半小时)。由于cron 没有达到亚分钟的分辨率,因此您需要找到另一种方法。
一种可能性,虽然有点杂乱无章(a),但有两个工作,一个偏移 30 秒:
# Need these to run on 30-sec boundaries, keep commands in sync.
* * * * * /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )
您会看到我添加了 cmets 并进行了格式化,以确保它们很容易保持同步。
cron 两个作业实际上每分钟运行一次,但后者会等待半分钟,然后再执行作业的“内容”/path/to/executable。
对于其他(非cron-based)选项,请参阅此处的其他答案,尤其是提到fcron 和systemd 的答案。假设您的系统能够使用它们(例如安装 fcron 或拥有带有 systemd 的发行版),这些可能更可取。
如果您不想想要使用 kludgy 解决方案,您可以使用基于循环的解决方案并稍作修改。您仍然需要设法让您的流程以某种形式运行,但是一旦排序,以下脚本应该可以工作:
#!/bin/env bash
# Debug code to start on minute boundary and to
# gradually increase maximum payload duration to
# see what happens when the payload exceeds 30 seconds.
((maxtime = 20))
while [[ "$(date +%S)" != "00" ]]; do true; done
while true; do
# Start a background timer BEFORE the payload runs.
sleep 30 &
# Execute the payload, some random duration up to the limit.
# Extra blank line if excess payload.
((delay = RANDOM % maxtime + 1))
((maxtime += 1))
echo "$(date) Sleeping for ${delay} seconds (max ${maxtime})."
[[ ${delay} -gt 30 ]] && echo
sleep ${delay}
# Wait for timer to finish before next cycle.
wait
done
诀窍是使用sleep 30,但在您的有效负载运行之前在背景中启动它。然后,payload完成后,等待后台sleep完成即可。
如果负载需要n 秒(其中n <= 30),则负载之后的等待时间将为30 - n 秒。如果花费的时间超过 30 秒,则下一个周期将延迟到有效负载完成,但不会再延迟。
您会看到我在那里有调试代码,从一分钟的边界开始,使最初的输出更容易理解。我也逐渐增加了最大有效载荷时间,所以你最终会看到有效载荷超过了 30 秒的循环时间(输出了一个额外的空白行,因此效果很明显)。
下面是一个示例运行(循环通常在上一个循环后 30 秒开始):
Tue May 26 20:56:00 AWST 2020 Sleeping for 9 seconds (max 21).
Tue May 26 20:56:30 AWST 2020 Sleeping for 19 seconds (max 22).
Tue May 26 20:57:00 AWST 2020 Sleeping for 9 seconds (max 23).
Tue May 26 20:57:30 AWST 2020 Sleeping for 7 seconds (max 24).
Tue May 26 20:58:00 AWST 2020 Sleeping for 2 seconds (max 25).
Tue May 26 20:58:30 AWST 2020 Sleeping for 8 seconds (max 26).
Tue May 26 20:59:00 AWST 2020 Sleeping for 20 seconds (max 27).
Tue May 26 20:59:30 AWST 2020 Sleeping for 25 seconds (max 28).
Tue May 26 21:00:00 AWST 2020 Sleeping for 5 seconds (max 29).
Tue May 26 21:00:30 AWST 2020 Sleeping for 6 seconds (max 30).
Tue May 26 21:01:00 AWST 2020 Sleeping for 27 seconds (max 31).
Tue May 26 21:01:30 AWST 2020 Sleeping for 25 seconds (max 32).
Tue May 26 21:02:00 AWST 2020 Sleeping for 15 seconds (max 33).
Tue May 26 21:02:30 AWST 2020 Sleeping for 10 seconds (max 34).
Tue May 26 21:03:00 AWST 2020 Sleeping for 5 seconds (max 35).
Tue May 26 21:03:30 AWST 2020 Sleeping for 35 seconds (max 36).
Tue May 26 21:04:05 AWST 2020 Sleeping for 2 seconds (max 37).
Tue May 26 21:04:35 AWST 2020 Sleeping for 20 seconds (max 38).
Tue May 26 21:05:05 AWST 2020 Sleeping for 22 seconds (max 39).
Tue May 26 21:05:35 AWST 2020 Sleeping for 18 seconds (max 40).
Tue May 26 21:06:05 AWST 2020 Sleeping for 33 seconds (max 41).
Tue May 26 21:06:38 AWST 2020 Sleeping for 31 seconds (max 42).
Tue May 26 21:07:09 AWST 2020 Sleeping for 6 seconds (max 43).
如果您想避免笨拙的解决方案,这可能会更好。您仍然需要cron 作业(或等效的)来定期检测此脚本是否正在运行,如果没有,则启动它。但是脚本本身会处理时间。
(a) 我的一些同事会说拼凑是我的专长 :-)