5

It's simple enough to use cron to schedule a job to occur periodically. I'd like to have something occur less regularly -- say, run the job, then wait 2 to 12 hours before trying again. (Any reasonable type of randomness would work here.) Is there a good way to do this?

2 Answers 2

10

You could use the command 'at'

at now +4 hours -f commandfile

Or

at now +$((($RANDOM % 10)+2)) hours -f commandfile
6
  • So schedule at to run every (say) 12 hours with cron, then have the at job happen a few hours later. Doable, though it would mean that the jobs happen more regularly than I want (no possibility of having it happen after 2 hours, then after 3 more hours after that, etc.).
    – Charles
    Commented Jul 25, 2014 at 16:37
  • Using this there is a 1 in 10 chance of it happening after only 2 hours, a 1 in 10 chance of it being after 3 hours, and so on up to 11 hours. $RANDOM % 10 will never return more than 9.
    – goldilocks
    Commented Jul 25, 2014 at 16:47
  • @Charles you can use 'seconds', 'mins' instead of 'hours'
    – jhilmer
    Commented Jul 25, 2014 at 17:01
  • @jhilmer: I want it to run repeatedly (in fact forever at these irregular intervals), not just once.
    – Charles
    Commented Jul 25, 2014 at 17:16
  • 1
    You could schedule the next job at the end of the current
    – jhilmer
    Commented Jul 25, 2014 at 17:23
6

Option 1

Schedule your job in cron to run every hour (or every other hour), but prefix the job with something like this (presuming you have SHELL=/bin/bash in your crontab):

[ $[RANDOM % 12] -eq 0 ] || exit 0; YOUR_JOB_HERE

Then there will be an approximately* one in twelve chance of the job running each time its scheduled.

Option 2

Schedule a cron job that, at the start of the day, figures out some random times and uses at to schedule all of today's runs. This is much more complicated, but will allow you to use different random distributions. E.g., you may want 2 hours to be much more likely than 12 hours.


Fine print

*This method of generating a random number is actually biased. The problem is that the maximum (32767) is not an even multiple of 12 (minus one). To see the problem clearly, compare if the maximum were 11 (12×1-1 = 11). 0 would yield 0, 1 would yield 1, etc. all the way through 11 yielding 11. But if it were 13 instead, 12 yields 0, and 13 yields 1. So 0 and 1 have two values that yield them, but 2–11 only have one value, so they're less likely. Hence, its biased. Switching to a formula using division by the maximum doesn't fix the problem, it just changes which numbers are biased against. Actual fixes are much more code (and basically involve faking the maximum being what you need it to be by trying again when it isn't).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .