Previously, I talked about creating a cron job for the last day of the month. This time around, I’m going to show how to set a cron job to run every so-many days. We’ll use every three days as an example.
If you know cron you’re probably thinking, “That’s easy!” Yes, it is. Here’s how we’d typically see that.
30 05 */3 * * execute_this
The above code will run the `execute_this` command at 5:30 am every three days, but what is the first day it will run? Let’s say it’s a brand new year. The noise makers are going and everyone is shouting “Happy new year!” What is the first day this command will run? January 1st? Actually, no. It will be January 3rd.
The “*/3″ can be seen as “every number evenly divisible by three.” That means it will always run on the 3rd of the month, the 6th of the month, the 9th, etc. That’s fine if that is what you’re after, but often (accounting tasks for example) you want it to run on the 1st of the month, the 4th, etc. How do we do that?
It’s very easy once you know. You see, that asterisk & slash combo we see frequently in crontabs isn’t the only way to go. It doesn’t have to be an asterisk; it can be any other value.
30 05 1-31/3 * * execute_this
This one will start on the 1st and run every three days from there until (and including) the 31st. This is how we get the offset to start on the 1st.
But That’s not REALLY Every Three Days!
No, it isn’t actually every three days. It is every three days of the month, but a new month resets at the first no matter when it was last run. And again, that’s good if that’s what you’re after.
If you actually need every three days of the year, here’s a bonus for you. We’ll have to make it work similarly to our “last day of the month” trick where we set the cron job to run each of the possible last days of the month and the command itself checked the date.
For this task, we’ll want the cron job to run every day, then check if the day of the year is evenly divisible by three – after accounting for our offset to start on the 1st of the year.
The command for “day of the year” is
Where the hyphen before the “j” means “don’t pad” (with zeros in this case – so we can use it as a number). Now we just check if this is evenly divisible by three by using the modulo – % – which returns the remainder of dividing.
$(( `date +%-j` % 3 ))
The $(( )) part tells bash to perform a calculation, and the backticks are there to run our date command separately from the rest. So if this calculation is zero, we have a winner.
[ $(( `date +%-j` % 3 )) == 0 ]
Remember, though, we need an offset so that we start on the 1st. The way it is currently, it starts on the 3rd. Just by subtracting one from the day of the year, we can get everything to line up. We have to wrap that calculation with $(( )) as well.
[ $(( $(( `date +%-j` - 1 )) % 3 )) == 0 ]
That test fulfills our conditions so our full crontab entry would be:
30 05 * * * [ $(( $(( `date +%-j` - 1 )) % 3 )) == 0 ] && execute_this