On Unix the universal job scheduler is "cron" (the other universal but less commonly known daemon is the at daemon). On Unix systems everywhere, lots and lots of batch jobs are kicked off all day from the cron daemon. The typical configuration looks something like this:
18 2 * * * ~/bin/some_batch_job
This means at 18 minutes past the hour at 2am on every day of the month of every month of every weekday, run the following command (You can read about the configuration format by typing man 5 crontab
on the command line of a nearby unix-y system).
Why 18 minutes past the hour? For an hourly job you often want to pick a "semi random" time of the hour to run the job. If you run the same batch job on several servers all accessing a shared resource for example.
Sometimes though then the configuration has to be exactly the same everywhere, but you still want to spread out the runs. Or it's a job that runs every minute or two on many systems. Or you have a system that just runs a lot of cronjobs and you can't have them all start at exactly the same second. You have to introduce second granularity to spread them out. But how? The cron format works with minutes at the lowest granularity.
You use the magic $RANDOM
variable in the shell!
You can get a random number by just accessing $RANDOM
, try it:
echo $RANDOM
If you want a number between 1 and 10 you do a modulo operation on the random variable. In shell syntax that'd be
echo $(expr $RANDOM % 10)
The $( ... )
syntax works like backticks, runs the command and returns the result. The expr command runs the arguments as a shell expression.
Now if you want to run a command (on average) every two minutes, but spread out the executions over 90 seconds, you can do
*/2 * * * * sleep $(expr $RANDOM \% 90); ~/bin/batch_job
This will run the cronjob every 2 minutes (120 seconds), but wait between 0 and 89 seconds before running the actual script. Magic!
Whenever you setup something to access a remote resource (RSS feed, NNTP server, ...) it's always polite to do this, otherwise the server operator will get an onslaught of requests exactly on the minute -- or even worse at the top of the hour.
random and modulo = not-so random
As $RANDOM returns values between 0 and 32767, $RANDOM mod 10 will return slightly more values of 0-7 than 8-9. Be careful where you use such a simple modulo!
Hi Odi,
Good point, thank you. I usually use it just for picking a number of seconds where the average number is as high or higher than the number of cronjobs I want to spread out, so it's been insignificant to me. I should have thought of mentioning it -- or at least not used 10 as an example. :-)
- ask
Be careful that your root's shell is ksh or bash - otherwise this won't work.