在https://unix.stackexchange.com/a/11105/674,吉尔斯写道
以下 crontab 行将
some_job
每 15 秒启动一次。* * * * * for i in 0 1 2; do some_job & sleep 15; done; some_job
该脚本假设作业的时间不会超过 15 秒。以下稍微复杂的脚本负责在运行时间过长的情况下不运行下一个实例。它依赖于
date
支持的%s
格式(例如GNU 或Busybox,所以你在Linux 上没问题)。如果直接将其放入 crontab 中,请注意字符必须按照crontab 行中的%
方式编写。\%
end=$(($(date +%s) + 45)) while true; do some_job & [ $(date +%s) -ge $end ] && break sleep 15 wait done [ $(date +%s) -ge $(($end + 15)) ] || some_job
不过,我要指出的是,如果您需要每 15 秒运行一次作业,那么 cron 可能是错误的方法。尽管 unice 非常适合短期进程,但每 15 秒启动一个程序的开销可能是不可忽略的(取决于程序的要求有多高)。您不能一直运行您的应用程序并让它每 15 秒执行一次任务吗?
这是正确的吗
该脚本不应该由 cron 运行;
该脚本尝试在从现在开始的一分钟内每 15 秒提交一次运行“some_job”的实例,并且如果已经有一个运行“some_job”的实例,则阻止提交下一个“some_job”实例?
break
当脚本在一分钟内的 45 到 59 秒之间第一次提交“some_job”实例时,将会执行。然后脚本会跳出 while 循环,跳过sleep
并wait
让实例完成运行。在循环外的下一个命令中,条件将为 false(因为现在的时间仍然在每分钟 45 到 59 秒之间),并且脚本将提交“some_job”的最后一个实例。现在有两个“some_job”实例正在运行,这是不希望的。正确的?
为什么不直接这样写脚本呢?
end=$(($(date +%s) + 60))
while true; do
some_job &
sleep 15
wait
[ $(date +%s) -ge $end ] && break
done
谢谢。
答案1
通过some_job
设置,( date; sleep 5; echo OK )
您将获得四个实例:每 15 秒一个。通过 20 秒延迟而不是 5 秒延迟(即( date; sleep 20; echo OK )
),您可以以 20 秒的间隔启动三个实例。
你的代码不起作用,这就是为什么你不能那样写。
顺便说一句,吉尔斯的代码也不适合我(我有五个实例,最后一个在第四个实例完成之前启动。)
这是我对代码的看法。通过 5 秒的工作,我获得了四次运行。通过 20 秒的工作,我得到了两次运行。
#!/bin/bash
#
echo START $(date)
some_job() { echo JOB BEGIN $(date); sleep 20; echo JOB END $(date); }
begin=$(date +%s)
interval=15
duration=60
while :
do
some_job
now=$(date +%s)
[[ $now -ge $((begin + duration)) ]] && break
rem=$(( (now - begin) % interval))
[[ $rem -eq 0 ]] && rem=interval
delay=$((interval - rem))
[[ $((now + delay)) -ge $((begin + duration)) ]] && break
sleep $delay
done
echo FINISH $(date)
作业完成后,此代码使用模运算%
符来确定下一个 15 秒间隔。然后,它会等到该时间到达后再重新启动作业。