Cron example
Cron Last Day of the Month
Standard Unix cron cannot express the last day of the month. The expression above is the pattern people copy from forum answers, and on its own it is wrong: it runs on every date from the 28th to the 31st, which is up to four runs a month instead of one. Making it correct requires a guard in the command.
By NaveenKumar T · Updated · 5-field crontab expression
What each field means
| Field | Value | Meaning |
|---|---|---|
| Minute | 0 | Minute 0 |
| Hour | 0 | Hour 0 |
| Day of month | 28-31 | Days 28–31 |
| Month | * | Every month |
| Day of week | * | Every day of the week |
Next 5 run times
Computing the next runs in your timezone…
What this expression really does
The day-of-month field matches any date in the range, so in January the job fires on the 28th, 29th, 30th and 31st; in April on the 28th, 29th and 30th; in a non-leap February only on the 28th. Cron has no concept of last, so it cannot know which of those dates ends the month. The plain-English translation this page shows you says exactly that, and it is worth reading before you deploy the line.
The fix is to keep the schedule and add a test to the command: run only if tomorrow is the first. On GNU coreutils that is a one-liner — [ "$(date -d tomorrow +%d)" = "01" ] && /path/to/job — and on BSD or macOS the equivalent uses date -v+1d. The scheduler fires up to four times; the guard lets exactly one of them through.
The L extension, and who has it
Several non-POSIX schedulers do support a last-day token. Quartz accepts L in the day-of-month field, along with L-3 for three days before the end and 5L for the last Friday. Spring's cron parser, croner and a number of cloud schedulers implement the same idea. If you are running on one of those, use L and delete the guard — it is unambiguous and self-documenting.
What you cannot do is assume it. Vixie cron, cronie and busybox crond will reject an L outright, and a crontab that fails to install is a job that never runs. Check your daemon's own manual page rather than a generic cron reference, because this is precisely where dialects diverge.
The better answer: run on the 1st instead
Most month-end work does not actually need to run on the last day — it needs to run after the month is over. Scheduling it at midnight on the 1st and having the job compute the previous month's date range is simpler, portable, and immune to leap years and month lengths alike.
It is also more correct in a subtle way. A job that runs at 23:00 on the 31st is summarising a month that has not finished; a job that runs at 00:05 on the 1st is summarising a month that has. If the deadline genuinely falls before midnight, keep the guard approach and document why in a comment above the crontab line.
Build a variant of this schedule with dropdowns and check the next ten runs before you install it.
Open the cron generatorRelated cron examples
Browse every schedule on the cron expression generator, read the cron expression syntax guide for the rules behind the five fields, or the developer tools guides for the longer explanations.