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:
interval=5*60*60 # 5 hours
if [[ ! -f /tmp/timestamp ]]; then
exit 0 # recreate timestamp and do work
if [[ $(( $(date +%s) - $(date -r "$timestamp" +%s) )) -lt $interval ]]; then
exit 1 # don't do work
touch "$timestamp" # update timestamp and do work
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: