Run a Cron Job on the Last Day of the Month
Months end on the 28th, 29th, 30th or 31st, and standard cron can't say 'whichever is last'. The portable approach schedules the job on all four candidate days and adds a guard that lets only the real last day through: [ "$(date -d tomorrow +\%d)" = "01" ] && /path/to/job. Quartz and AWS EventBridge support an L shortcut for this, but classic cron does not.
0 0 28-31 * *In plain English: At 00:00 (midnight), on day 28 through 31 of the month.
Field by field
| Field | Value | Meaning |
|---|---|---|
| Minute | 0 | 0 |
| Hour | 0 | 0 |
| Day of month | 28-31 | 28 through 31 |
| Month | * | every month |
| Day of week | * | every weekday |
Variations
0 0 28-31 * *all candidate days — always pair it with the date guard0 23 28-31 * *23:00 on the last day, for end-of-day jobs (same guard)0 0 1 * *midnight on the 1st — often equivalent, with no guard neededTweak any of these in the crontab explainer to see the schedule in plain English and its next run times.
Frequently asked questions
Why does my date check do nothing in crontab?
Cron treats % as a newline in the command field, so +%d breaks the line. Escape it as +\%d, or move the check into a script, where % needs no escaping. On macOS, use date -v+1d +%d instead of GNU date's -d tomorrow.
Is there an L option in cron?
Not in standard cron (Vixie cron, cronie). Quartz, AWS EventBridge and a few other schedulers support L for 'last day of the month'; check your scheduler's documentation before relying on it.
New to cron syntax? Read Cron Expressions Explained, Field by Field. Job not firing? Work through Cron Job Not Running? 10 Things to Check.