tl;dr [[ $(date +%d -d 1day) = 01 ]] or 0 0 1 * *.

Some cron implementations support L as the last day of week or month, which is nonstandard, that I was aware of since 6/18/2014, 8:36:39 AM and had checked1 the documentations of anacron, bcron, cronie, dcron, fcron, incron, and vixie-cron, they didn’t support L.

1   Simpler solution

While writing this post, I realized that the simple solution is a bit of over thinking. If next day is the first day of next month, then today is the last day of the month; it also means the next day would be of the day number of 1, that is doing this simpler way:

[[ $(date +%d -d 1day) = 01 ]] && echo true

2   Simple solution

Dennis Miller wrote a simple line to achieve the similar result:

[ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true

I tweaked it a bit and came up with these, a few letter shorter versions2:

expr $(date +%d -d 1day) != $(date +%d) + 1 && echo true
let $(date +%d -d 1day)!=$(date +%d)+1      && echo true

(($(date +%d -d 1day) - $(date +%d) != 1))  && echo true
(($(date +%d -d 1day) - $(date +%d) - 1))   && echo true
(($(date +%d -d 1day) - ++$(date +%d)))     && echo true

(($(date +%d -d 1day) - $(date +%d) < 1))   && echo true
(($(date +%d -d 1day) != $(date +%d) + 1))  && echo true
(($(date +%d -d 1day) != ++$(date +%d)))    && echo true

This one is my favorite if I ever need to run a cron job on the end of the month:

(($(date +%d -d 1day) - ++$(date +%d))) && echo true

It’s simple and use Bash’s syntax to full potential, you get the day of month of next day and today’s from date, increase today’s by 1. If they are equal, then it’s still not the last day. In other words or in the code above, you subtract one from another, if it’s 0, meaning equal, then it’s not the end, otherwise, it is the end.

3   Run from the other side

Sometimes, the truly simple solution is to step out and look at the whole problem. Question you must ask is why do you need to run in the end of the month? Are you going to generate some analytics for the month? If so and if you do run in the end, say 23:59, wouldn’t you possibly lose an 1 minute data? Shouldn’t you run it in the beginning of the next month?

Unless you are going to prepare something for next month, you might not actually need to run on the last day, and perhaps the first 1 minute of the first day would be enough for the preparation, then you really don’t need to run on the last day.

I couldn’t remember why I need the last day cron schedule, or maybe it just came to my mind and I wanted to know an answer for that. Either way, I was caught up in that thought of having the last day and nothing else, unable to get out of the loop of thinking until I read the comment by Rodnee.

I once had a similar issue, but failed to come up with a solution for the last day of the month. There was a very simple answer for my particular case as all I needed to do was run the scripts on the first of the month. But your solution looks pretty nifty! Thanks.

So, it would be like:

0 0 1 * * echo true
# or, if nonstandard predefined scheduling definitions are supported
@monthly  echo true

It doesn’t explain much about his actual requirements, but it really is very simple. Occasionally, you just need to change your thought pattern, walk out and take a good look of your problem rather than trying to solve it with fixed path.


[1]Checked as of 2015-02-09.
[2]I couldn’t help myself, I must align &&.