CRON Last Day of Month — What Works and What Breaks
💡Standard five-field cron has no universal built-in token for the last day of the month. Most teams use a shell check or scheduler extension, then verify the result with ToolDock CRON Parser.
Pattern Examples
Non-portable `L` token
❌ Wrong
0 0 L * * /srv/app/month-end.sh✅ Fixed
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /srv/app/month-end.sh`L` works in Quartz-like systems, not in plain cron everywhere.
Unsafe day 31 shortcut
❌ Wrong
0 0 31 * * /usr/local/bin/close-books✅ Fixed
0 23 28-31 * * [ "$(date +\%m -d tomorrow)" != "$(date +\%m)" ] && /usr/local/bin/close-booksDay 31 misses shorter months.
Wrong monthly assumption
❌ Wrong
0 0 30 * * python cleanup.py✅ Fixed
55 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && python cleanup.pyDay 30 also misses February and some end-of-month cases.
Test Your Schedule
Real-World Usage
Month-end finance close
0 23 28-31 * * [ "$(date +\%m -d tomorrow)" != "$(date +\%m)" ] && /usr/local/bin/close-booksRuns only when tomorrow is a new month.
Retention cleanup
55 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && python cleanup.pyChecks whether the next day is the first, then runs cleanup.
Extended scheduler
0 0 L * * /srv/app/month-end.shSome schedulers support `L`, but plain cron often does not.
Related Guides
Frequently Asked Questions
Can cron run on the last day of the month?
Plain cron cannot do that portably with a single built-in token, so most teams use a shell condition or a richer scheduler.
Does `L` work in normal cron?
Not reliably. `L` is common in Quartz syntax, but many standard cron implementations reject it.
What is the safest workaround for last day of month?
Run on days 28 through 31 and gate execution with a shell check that confirms tomorrow starts a new month.
All tools run in your browser. Your data never leaves your device.