Cron expressions explained (for people who forget them every time)
The five fields, the special characters, and the schedules everyone actually uses. A field guide for anyone who Googles 'cron every 5 minutes' more than once a month.
The five fields
Standard Unix cron is five space-separated fields, in this order:
* * * * *
| | | | |
| | | | +-- day of week (0-6, Sunday = 0)
| | | +---- month (1-12)
| | +------ day of month (1-31)
| +-------- hour (0-23)
+---------- minute (0-59)
Each field accepts:
- A single number โ
5means "5" (5 minutes past the hour if in the minute field). - A range โ
1-5means "1, 2, 3, 4, 5". - A list โ
1,3,5means "1 or 3 or 5". - A step โ
*/15means "every 15" (from 0).10-30/5means "every 5 within 10-30". - A wildcard โ
*means "every value".
That's the entire grammar. Everything else is convenience.
The schedules everyone actually uses
Bookmark this table and you'll never Google "cron every 5 minutes" again:
* * * * *โ every minute.*/5 * * * *โ every 5 minutes.0 * * * *โ every hour, on the hour.0 */3 * * *โ every 3 hours.0 0 * * *โ midnight every day.0 9 * * 1-5โ 9 AM every weekday.0 9 * * 1โ 9 AM every Monday.30 3 * * 0โ 3:30 AM every Sunday.0 0 1 * *โ midnight on the 1st of every month.0 0 1 1 *โ midnight on January 1st (annually).
The special strings
Most cron implementations accept these shortcuts:
@yearly(or@annually) โ0 0 1 1 *@monthlyโ0 0 1 * *@weeklyโ0 0 * * 0@daily(or@midnight) โ0 0 * * *@hourlyโ0 * * * *@rebootโ run once at boot (event-triggered, not a schedule).
Portable across most Linux distros. Not supported by every cron implementation (BusyBox cron on Alpine, for instance, only supports @reboot).
The gotchas that cost real time
Timezones. Your server's crontab runs in the server's timezone. If your server is in UTC and you want a job at 9 AM Eastern, use 0 14 * * * (or 0 13 * * * in daylight saving time โ which is why "9 AM Eastern" schedules break twice a year). Better: set CRON_TZ=America/New_York at the top of the crontab if your cron supports it.
Day-of-month and day-of-week are OR'd. 0 0 1 * 1 runs at midnight on either the 1st of any month OR every Monday โ not "midnight on the 1st only if it's a Monday". If you want an AND, use two separate cron entries or check the day inside your script.
Environment variables. Cron runs jobs with a stripped-down environment. PATH is often just /usr/bin:/bin. Your script that works interactively may fail from cron because node, python, or aws aren't on the path. Fix: use absolute paths, or set PATH at the top of the crontab.
Output silently emailed (or lost). By default cron mails stdout/stderr to the local user. On modern servers with no mail daemon, the output vanishes. Redirect: 0 * * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1.
Overlapping runs. Nothing prevents a slow job from starting again while the previous run is still going. Wrap with flock: 0 * * * * flock -n /tmp/backup.lock /usr/local/bin/backup.sh.
Quartz cron: don't confuse it with Unix cron
Java's Quartz scheduler, Spring's @Scheduled, and AWS EventBridge use a 6- or 7-field cron with seconds and years. Quartz also supports ?, L (last day of the month), W (nearest weekday), and # (nth day of the month). None of these work in standard Unix cron.
If you're setting up a Kubernetes CronJob, Linux crontab, or GitHub Actions schedule: 5 fields, no seconds. If you're setting up Spring, Quartz, or AWS EventBridge: 6-7 fields with seconds.
Cron Generator targets standard 5-field Unix cron, since that's what 90% of scheduling systems use.
The verification workflow
Building a cron expression is a two-step debug cycle:
- Write the expression โ pick minute, hour, day, etc.
- Verify the next N run times match what you meant.
Step 2 is the one everyone skips. It's also the one that catches "wait, I wrote day-of-week when I meant day-of-month" before it hits production.
Cron Generator shows a plain-English translation and the next 5 run times as you build the expression. Paste an existing crontab entry to explain it โ often faster than re-deriving what past-you meant.
Related tools:
- Regex Tester โ when your cron job is grep-ing log files and you need to check the pattern.
- JSON Formatter โ when the job's output is JSON and you need to eyeball it.