Cron to Run on First Tuesday of the Month

I had a reasonable request come in this week whereby a reporting URL needs to be hit at a scheduled time. The required schedule was the first Tuesday of each month. Sounds reasonable right?

So I SSH’ed onto the box and opened up “crontab -e -ureportuser” where we store these kind of things. Then I started to think for a minute how I was going to go about this. I suddenly realised I wasn’t sure and turned to my trusty friend, Google.

Sigh, I don’t know what it was but Google was letting me down today. I wanted to find the most effective and neat way of doing this. I didn’t want to call some hacked up bash script, it had to be neat, easy and maintainable with no overhead calling additional scripts.

Why isn’t it straight forward? I simply want to run a report via cron on first Tuesday of the month. Darn, it could be a Monday, Wednesday, Thursday or any other day! Windows can do it easily, but who wants to use Windows for this kind of thing! Blah!

The closest I came up to was this:

5 9 1-7 * 2 /bin/email-report.sh

5 = minutes 0:05
9 = hour 9am
1-7 = calendar day 1 to 7, as the first Tue has to be in this range
* = month, all
2 = weekday Tue
/bin/email-report.sh = command

It looks fine on paper except for one thing. The 2 (Tuesday) weekday setting comes through as an OR and not an AND. So the report was running on every applicable Tuesday and the first seven days of the month. Drat! The client shouldn’t have gotten that report yet?

A colleague (Gavin – thanks bro!) however came up with a delightful solution that had me impressed. It’s neat, tidy, maintainable and no extra scripts – within all the rules.

5 9 * * 2 [ `date +\%d` -le 7 ] && /bin/email-report.sh

5 = minutes 0:05
9 = hour 9am
* = calendar day, all
* = month, all
2 = weekday Tue
[ `date +\%d` -le 7 ] && /bin/email-report.sh = command

How does this work? [ `date +%d` -le 7 ] && forms a conditional statement in bash that will return an exit code based on whether the condition is true or false. In the condition is true the report gets run. Note that when we add this to a crontab entry, the % will need to be delimited with a backslash (\).

Broken down, the backquotes or backticks indicate command substitution, meaning the contents will be evaluated in bash. `date +%d` will evaluate into calling of the date command with the attribute +%d – which will return the current numeric day of the month (e.g. 03).

The remainder of the conditional statement (-le 7) asks if the resulting day of the month is less than or equal than seven. If the result is less than or equal to seven, then it is within the first seven day or week of the month and a true (1) is returned. Otherwise a false (0) exit code is returned and further execution halts.

If this command [ `date +\%d` -le 7 ] && /bin/email-report.sh is run on every Tuesday of the month, eventually it will run within the first seven days and execute the report!

This command could be easily modified to run on the second, third, forth or fifth specified weekday of the month – whatever you require.

This entry was posted in Linux, SSH. Bookmark the permalink.

18 Responses to Cron to Run on First Tuesday of the Month

  1. Pingback: Cron: Run every thursday before last Sunday of the month | shareitHQ

Leave a Reply

Your email address will not be published. Required fields are marked *