A few weeks back, a user asked me about running an automated task
every other week. Though most of us use cron as needed to run those nice little tasks that clean up core files and evaluate the contents of log files in the middle of the night, running a task every other week or every other day presents a bit of a challenge. The cron command doesn’t have any way to express odd or even weeks.
The general “trick” that I use for tasks such as these is to ask cron to
run the task every week or every day and then insert logic into the
script itself to determine whether the week is odd or even.
Using this strategy, a cron entry that looked something like this:
8 8 * * 3 /usr/local/bin/send_msg
that would be executed every Wednesday might be calling a script that examines the date and continues only when it’s running on an odd or even week.
A shell (/bin/sh) script to send a message on even weeks might look
something like this:
ON_WK=`expr $WK % 2`
if [ $ON_WK = 1 ]; then
cat /opt/stats/msgs | mailx -s “stats report” email@example.com
This same strategy can be used for tasks that need to be performed every other hour, every third week, every seven minutes or almost any other interval that you might want to work with. For intervals that align nicely with cron’s timing fields (minutes after the hour, hour, day of the month, month and day of the week, there’s no good reason not to put all of your timing logic into the cron file. When your needs don’t align well with these columns, on the other hand, or when you want to avoid putting lines like these into the cron file:
0,4,8,12,16,20,24,28,32,36,40,44,48,52,56 * * * * /usr/local/bin/chk_log
constraining the time within the script itself is not such a bad idea.
The number 2 in the “ON_WK=`expr $WK % 2`” line of the scrip represents the modulo operation. For anyone who isn’t used to these, the result of an “expr <number> % <modulus>” operation is what you’d be left with if you removed the modulus as many times as you could. Because our modulus is 2, the result is 0 or 1. Were the modulus 5, we could get any value between 0 and 4.
The “WK=`date +%W`” command uses an argument to the date command to obtain the number of the current week. You’d expect these to run from 1 to 52 or thereabouts. So the combination gives us a 1 if the current week is odd and a 0 otherwise.
Other date command options that can be used with this kind of logic
%d – date within the month (e.g., 21)
%m – month number (1-12)
%H – hour (0-23)
%M – minute (0-59)
%S – second (0-59)
To run a script every other day, you couldn’t rely on the day of the
month. This would only work for a while. You’d soon find yourself moving from one odd day to another. This would happen any time you got to the end of a month with 31 days. Instead, you would use the value that represents the day of the year. You’d expect these to run from 1 to 365 except, of course, on leap years. If the end-of-the-year problem concerns you, you could probably perform some much more complex calculation to be sure you’re still running every other day but, for most of us, an adjustment at the end of each calendar year is probably not too big an issue. We could always switch our running from odd to even days if the need for regularity was sufficiently important.