In https://unix.stackexchange.com/a/11105/674, Gilles wrote
The following crontab line will start
some_job
every 15 seconds.* * * * * for i in 0 1 2; do some_job & sleep 15; done; some_job
This script assumes that the job will never take more than 15 seconds. The following slightly more complex script takes care of not running the next instance if one took too long to run. It relies on
date
supporting the%s
format (e.g. GNU or Busybox, so you'll be ok on Linux). If you put it directly in a crontab, note that%
characters must be written as\%
in a crontab line.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
I will however note that if you need to run a job as often as every 15 seconds, cron is probably the wrong approach. Although unices are good with short-lived processes, the overhead of launching a program every 15 seconds might be non-negligible (depending on how demanding the program is). Can't you run your application all the time and have it execute its task every 15 seconds?
Is it correct that
the script is not supposed to run by cron;
the script tries to submit an instance of running "some_job" as close as to once every 15 seconds within a minute from now, and prevent submitting the next instance of "some_job" if there is already an instance running "some_job"?
The break
will execute, when the script just submit an instance of "some_job" for the first time between 45 and 59 second in the minute. Then the script just breaks out of the while loop, skipping sleep
and wait
for the instance to finish running. In the next command outside the loop, the condition will be false (because the time right now is still between 45 and 59 second in the minute), and the script will submit the last instance of "some_job". Now there are two instances of "some_job" running, which is undesired. Correct?
Why not just write the script this way?
end=$(($(date +%s) + 60))
while true; do
some_job &
sleep 15
wait
[ $(date +%s) -ge $end ] && break
done
Thanks.