Possibly the easiest way is to simply do three separate jobs:

55 23 30 4,6,9,11 * myjob.sh 55 23 31 1,3,5,7,8,10,12 * myjob.sh 55 23 28 2 * myjob.sh

That will run on the 28th of February though, even on leap years so, if that's a problem, you'll need to find another way.

However, it's usually both substantially easier and correct to run the job as soon as possible on the first day of each month, with something like:

0 0 1 * * myjob.sh

and modify the script to process the previous month's data.

This removes any hassles you may encounter with figuring out which day is the last of the month, and also ensures that all data for that month is available, assuming you're processing data. Running at five minutes to midnight on the last day of the month may see you missing anything that happens between then and midnight.

This is the usual way to do it anyway, for most end-of-month jobs.

If you still really want to run it on the last day of the month, one option is to simply detect if tomorrow is the first (either as part of your script, or in the crontab itself).

So, something like:

55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh

should be a good start, assuming you have a relatively intelligent date program.

If your date program isn't quite advanced enough to give you relative dates, you can just put together a very simple program to give you tomorrow's day of the month (you don't need the full power of date ), such as:

#include <stdio.h> #include <time.h> int main (void) { // Get today, somewhere around midday (no DST issues). time_t noonish = time (0); struct tm *localtm = localtime (&noonish); localtm->tm_hour = 12; // Add one day (86,400 seconds). noonish = mktime (localtm) + 86400; localtm = localtime (&noonish); // Output just day of month. printf ("%d

", localtm->tm_mday); return 0; }

and then use (assuming you've called it tomdom for "tomorrow's day of month"):

55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh