我可以使用下面的代码设置每 5 小时一次的 cron 作业吗?
0 */5 * * * script.sh
我的 script.sh 将在什么时候执行?
- 0000、0500、1000、1500、2000、0100、0600、1100、1600、2100 等等...
或者
- 0000、0500、1000、1500、2000、0000、0500、1000、1500、2000 等等...
如果我们不能用这种传统方法设置每 5 小时一次的 cron 作业,还有其他方法来设置这样的作业吗?
答案1
一个 cron 作业指定为
0 */5 * * * script.sh
将作为您的第二个选项运行,在 20:00 和 00:00 之间的作业间隔四个小时。
您可以尝试使用五种工作规范:
0 0-20/5 1-31/5 * * script.sh
0 1-21/5 2-31/5 * * script.sh
0 2-22/5 3-31/5 * * script.sh
0 3-23/5 4-31/5 * * script.sh
0 4-19/5 5-31/5 * * script.sh
第三个字段是该月的日期。这将使您的工作在有五天倍数的月份中每五个小时完美运行一次。在其他月份,您会遇到同样的问题,即该月的最后一次作业运行与新月份的第一次运行之间的延迟太短。
这可能没问题。如果不是,您可能需要考虑在无限循环中将作业作为后台作业运行,并内置 5 小时的延迟。
#!/bin/sh
while true; do
script.sh &
sleep 18000 # 5h
done
上面是一个在后台运行的控制脚本。
在大量迭代之后,这显然会开始轻微漂移,并且您可能很难准确地在整点开始它。
另一个想法是让脚本本身使用以下命令重新安排自身at
:
#!/bin/sh
echo script.sh | at now + 5 hours
# rest of script goes here.
答案2
另一种方法是让 cron 每小时启动一个脚本,但每五个小时才执行一次实际工作。或者,更简单的是,仅当自上次运行以来已经过去至少 5 小时。我们可以创建一个小脚本来使用文件作为时间戳。
在 GNU 系统上,此脚本应该可以工作:
#/bin/bash
timestamp=/tmp/timestamp
interval=5*60*60 # 5 hours
if [[ ! -f /tmp/timestamp ]]; then
touch "$timestamp"
exit 0 # recreate timestamp and do work
fi
if [[ $(( $(date +%s) - $(date -r "$timestamp" +%s) )) -lt $interval ]]; then
exit 1 # don't do work
fi
touch "$timestamp" # update timestamp and do work
exit 0
(date -r
是 GNU,在 FreeBSD 上我认为你可以使用stat +%m "$timestamp"
它。)
使用 crontab 行运行,例如
0 * * * * /foo/every5h.sh && /foo/do_the_actual_job.sh
这可能会出现这样的问题:如果脚本执行延迟,时间戳可能会在该小时后几秒更新,而 5 小时后,完整的 5*60*60 秒还没有到。我们可以通过将脚本中的时间间隔设置为interval=5*60*60-15
允许在上一次运行之后的 04:59:45 开始新的运行来解决这个问题。由于脚本本身每小时仅启动一次,因此这不会使工作时间发生变化。
如果系统出现故障,并且已经过去了 5 个多小时,则工作将在下一个小时继续进行。另外,按照我上面写的方式,如果时间戳文件被删除,它将重新创建和这项工作将在下一个小时进行。
至少有类似的答案:
答案3
如果将其设置为每 5 小时,则为每 5 小时,所以 0、5、10、15、20、1、6 等...(*/5 语法)
如果您需要将其设置为 0 5 10 15 20 0 5 10 等...您必须明确指定它
0 5,10,15,20,0 * * * somejob