我想知道 cron 计时的准确性和确定性如何。假设我让 cronjob 在 11:00:00 运行,然后我将时间作为该 cron 作业的参数。在任何情况下,参数中的时间是否有可能不同,例如 11:00:01。我可以 100% 确定执行会在准确的时间发生吗?我担心服务器负载过重或任何不可预见的情况等问题。有什么可以影响它吗?我假设可以。
我还想知道如何将计划的执行时间作为参数传递,而不是实际时间。假设实际执行较晚,例如 11:00:01。如何通过 cronjobs 中定义的计划时间(例如 11:00:00),以及当 cron 作业设置为每 10 分钟运行一次时如何执行此操作?在这种情况下是否可以获取计划时间,以便每次执行脚本时都将计划时间作为参数?
10 * * * * /tmp/script.sh $(date)
答案1
只需检查我自己的系统日志,我就可以看到 cron 作业通常在每分钟过去 1 秒开始(Ubuntu 20.04)。 (例如:五十分十分触发于05:10:01
)。在我的系统上,这非常稳定,但我不会保证它。
在重负载下,这可能会更糟,因为即使 cronjob 在正确的时间触发,极其重负载可能会延迟挖掘超过一秒。但是这样的极端负载会减慢您的脚本速度,以至于启动时间将变得毫无意义。
Cron 可以并且确实偶尔会跳过作业,例如,如果系统关闭,它永远不会跟上。我会特别注意这个注释手动的:
请注意,这意味着不存在的时间(例如夏令时转换期间的“缺失时间”)将永远不会匹配,从而导致在“缺失时间”期间安排的作业无法运行。同样,出现多次的时间(同样是在夏令时转换期间)将导致匹配作业运行两次。
确保您的代码在 05:10:02 而不是 05:10:01 运行时不会中断。
没有优雅的方法可以让 cron 告诉您哪个作业正在运行。您可以设置许多相同的作业在不同的时间运行,每个作业都可以将时间作为参数传递。我看到两个选择:
设置一个包含许多条目的 crontab
请检查下面的注释。
是的,一天有 1440 分钟,所以如果您需要一个 crontab 来运行这一分钟,您可能需要一个脚本来生成您的 crontab:
#!/bin/bash
for hour in {0..23} ; do
for minute in {0..59} ; do
echo "${minute} ${hour} * * * root /path/to/script.sh ${hour}:${minute}:01"
done
done > /etc/cron.d/my-job
你最终会得到这样的结果:
01 00 * * * root my-job 00:01:01
02 00 * * * root my-job 00:02:01
03 00 * * * root my-job 00:03:01
...
创建一个包装脚本来查找最接近的预期运行
最好创建一个包装脚本来检查当前时间并查找最近的条目。如果您的作业设置为每 15 分钟运行一次,您可以使用此处提供的示例:
#!/bin/bash
curdate=`date "+%s"`
run_time=$(($curdate - ($curdate % (15 * 60))))
run_time_arg=$(date -d"@$run_time" "+%H:%M:%S")
/path/to/script.sh $run_time_arg
请注意,这确实使用了 GNU 特有的行为date
,并且可能不适用于所有实现