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.

VN:F [1.9.10_1130]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.10_1130]
Rating: +4 (from 4 votes)
Leave a comment

How to Stop sidebar.exe Using Lots of Memory (Edited 14 May 2011)

One of my readers, TED has made a suggestion as to a hack fix to the sidebar.exe memory problem (as documented in my blog post Windows sidebar.exe Memory Leak). With some spare time at the moment, I’ve been able to implement his suggestion and confirm it works.

I’ve written a batch script, and confirmed this works in Windows 7 (should work in Windows Vista too). I created a batch file called restart-sidebar.bat, and stored it in c:\users\brendan – contents of the file below:

@echo off
taskkill /im sidebar.exe /f
echo This script will now sleep momentarily…
TIMEOUT /T 2
echo Starting sidebar.exe now…
start sidebar.exe

The idea is it will kill the process called / task with the image name of, sidebar.exe, forcefully. It will then wait two seconds before starting the process again.

To complete the setup, create a new scheduled task specifying the path to your newly created batch file (mine was c:\users\brendan\restart-sidebar.bat). Run the scheduled task as your own user. I have it scheduled to run once a day at 5pm. I prefer to have it run when I’m not using the computer, more of a scheduled maintenance task that goes on behind the scenes. If you find that’s not enough, schedule it to run a few times a day.

For your information – I’ve encountered on only a few occurrences problems in the past when shutting. The sidebar process has stalled the shutdown procedure and Windows has forcefully killed the process. On login again I’ve lost a few sidebar settings. While I’ve not encountered this running the above batch script, it’s possible you may encounter this. If you’re concerned about it, drop the /f from the taskkill line in the above script (as to not force it) and increase the timeout value from 2, to up to 20 seconds to allow it to safely exit.

Downsides / Cons - I haven’t been able to find something to force the batch file to run in a minimised window (so it pops up and runs as a black command prompt window). This I’m a little bit disappointed with – you could perhaps create a shortcut to the batch file and set the properties on it to start minimised – however I’ve not confirmed this works. – See “Edit 14 May 2011″ below which overcomes this problem.

Advantages / Pluses - It’s a simple and easy fix. Avoids the pain of closing all your programs and restarting / logging off. Runs in seconds and doesn’t require administrative privileges to run.

Edit 14 May 2011 - I recently received an interesting email sent via the contact page. Ray, a fellow sysadmin in the trenches, had come up with a beautiful revision to my own code above. Using the below Windows Script in a vbs file (e.g. restart_sidebar.vbs) run on the same scheduled task as above, it accomplishes the restart of the sidebar without any extra windows or user interaction – it runs silently in the background (like a ninja). I’ve tested it for a few days and it runs beautifully. Thanks Ray, and good work!

‘—————————————————
‘ Author: Ray Flores (raymond.l.flores@gmail.com)
‘ Written May 2011
‘—————————————————

Set WshShell = WScript.CreateObject(“WScript.Shell”)
WshShell.Run “C:\Windows\System32\taskkill.exe /im sidebar.exe /f”, 0, True
WshShell.Run “C:\Windows\System32\timeout.exe /T 2″, 0, True
WshShell.Run “sidebar.exe”, 0, True

VN:F [1.9.10_1130]
Rating: 4.5/5 (2 votes cast)
VN:F [1.9.10_1130]
Rating: +10 (from 10 votes)
1 Comment