在分钟指示符中有*/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 )
您将看到我添加了注释并进行了格式化,以确保它们易于保持同步。
这两个cron作业实际上每分钟运行一次,但后者在执行作业的“肉”/path/to/executable之前会等待半分钟。
关于其他(非基于cron的)选项,请参阅这里的其他答案,特别是提到fcron和systemd的答案。假设你的系统有能力使用它们(比如安装fcron或者有一个带有systemd的发行版),这些可能是更可取的。
如果您不想使用这个笨拙的解决方案,您可以使用一个基于循环的解决方案,并进行了一个小的修改。你仍然需要管理保持你的进程以某种形式运行,但是,一旦排序,下面的脚本应该工作:
#!/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,但在有效负载运行之前在后台启动它。然后,在有效负载完成后,只需等待背景睡眠完成。
如果有效载荷需要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)我的一些同事会说拼板是我的专长:-)