5

Can I use below code to set cron job for every 5 hours?

0 */5 * * * script.sh

What time my script.sh will be executed?

  1. 0000, 0500, 1000, 1500, 2000, 0100, 0600, 1100, 1600, 2100 and so on...

OR

  1. 0000, 0500, 1000, 1500, 2000, 0000, 0500, 1000, 1500, 2000 and so on...

If we can not set cron job for every 5 hours with this traditional method, is there any other way to set such job?

8

A cron job specified as

0 */5 * * * script.sh

would run as your second option, with four hours between the job at 20:00 and 00:00.

You could try using five job specifications:

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

The 3rd field is the day of the month. This would run your job perfectly every five hours on months that have a multiple of five days. On other months, you would have the same issue with a too short delay between the last job run of the month and the first run in the new month.

This may be okay. If it's not, you may want to consider running the job as a background job in an infinite loop with a 5 hour delay built-in.

#!/bin/sh

while true; do
    script.sh &
    sleep 18000   # 5h
done

The above would be a controlling script that would run in the background.

This would obviously start drifting ever so slightly after a large number of iterations, and you may have difficulties starting it exactly on the hour.

Another idea is to let the script itself reschedule itself using at:

#!/bin/sh

echo script.sh | at now + 5 hours

# rest of script goes here.
2

Another way to do this is to have cron start a script every hour, but only do the actual work every five hours. Or, more easily, only if at least 5 hours has passed since the last run. We can create a small script to use a file as a timestamp.

On a GNU system, this script should work:

#/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 is GNU, on FreeBSD I think you could use stat +%m "$timestamp" instead.)

Run with a crontab line like

0 * * * * /foo/every5h.sh && /foo/do_the_actual_job.sh

That may have the problem that if the script execution got delayed, the timestamp might be updated some few seconds past the hour, and 5 hours later on the hour, the full 5*60*60 seconds would not yet be up. We could combat that by making the interval in the script something like interval=5*60*60-15 to allow a new run already only 04:59:45 after the last one. Since the script itself is launched only once an hour, this wouldn't make the work times drift.

If the system was down, and more than 5 hours had passed, the work would run on the next hour. Also, the way I wrote it above, if the timestamp file was deleted, it would be re-created and the work would run on the next hour.

There's similar answers like this in at least:

-2

If you set it to every 5 hours it is every 5hours so on 0, 5, 10, 15, 20, 1, 6, etc... (*/5 syntax)

if you need to set it on 0 5 10 15 20 0 5 10 etc.... you have to specify it explicitly with

0 5,10,15,20,0 * * * somejob
8
  • Note that there will be 4 hours between the job running at 20:00 and the one running at 00:00. – Kusalananda May 17 '19 at 17:46
  • that's why there are two different syntaxes for both cases – francois P May 17 '19 at 17:47
  • 1
    I don't understand, */5 is identical to 0,5,10,15,20, which is what your cron job schedule amounts to. – Kusalananda May 17 '19 at 17:50
  • 1
    It's still only 4 hours between 20:00 and 00:00. – Kusalananda May 17 '19 at 18:29
  • 1
    I'm quite sure something like 0 */5 * * * will not roll over the count from one day to the other, but will in fact do exactly the same as 0 0,5,10,15,20 * * *. (If it did roll over, what hour would it start?) Of course, this isn't a problem for */2, */3, */4, */6, */8 or */12 hours (or */5, */10, */15, etc. minutes), but 24 doesn't divide evenly by 5. – ilkkachu May 30 '20 at 11:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.