A cron expression is a string of 5 (or 6) fields that defines a recurring schedule for running automated tasks. It is the standard format used in Unix cron jobs, CI/CD pipelines, cloud schedulers (AWS EventBridge, GitHub Actions), and most backend job frameworks.
Inspect the next run times with the cron parser. Confirm the scheduler’s timezone and supported dialect before deploying the expression.
What does each field in a cron expression mean?
┌─────────── minute (0–59)
│ ┌───────── hour (0–23)
│ │ ┌─────── day of month (1–31)
│ │ │ ┌───── month (1–12 or JAN–DEC)
│ │ │ │ ┌─── day of week (0–6 or SUN–SAT, 0=Sunday)
│ │ │ │ │
* * * * *Some systems add a 6th field for seconds (Quartz, Spring) at the beginning, or a 6th year field at the end.
What do the special characters (* , - / L W #) do?
| Character | Name | Meaning |
|---|---|---|
| * | Wildcard | Every value in the field |
| , | List | Multiple values: 1,3,5 |
| - | Range | A range of values: 1-5 |
| / | Step | Every N values: */5 = every 5 minutes |
| L | Last | Last day of month or week (some implementations) |
| W | Weekday | Nearest weekday to given day (some implementations) |
| # | Nth | 3rd Monday = MON#3 (some implementations) |
What are common cron schedule examples?
* * * * *Every minute*/5 * * * *Every 5 minutes0 * * * *Every hour (at :00)0 */2 * * *Every 2 hours0 9 * * *Daily at 9:00 AM0 0 * * *Daily at midnight0 9 * * MON-FRIWeekdays at 9:00 AM0 9 * * 1Every Monday at 9:00 AM0 0 1 * *First day of every month at midnight0 0 1 1 *Once a year on January 1st at midnight30 8 * * 1-5Weekdays at 8:30 AM0 0,12 * * *Twice daily: midnight and noon0/30 * * * *Every 30 minutes (Quartz syntax)Can I use month and day-of-week names instead of numbers?
Months
| Number | Name |
|---|---|
| 1 | JAN |
| 2 | FEB |
| 3 | MAR |
| 4 | APR |
| 5 | MAY |
| 6 | JUN |
| 7 | JUL |
| 8 | AUG |
| 9 | SEP |
| 10 | OCT |
| 11 | NOV |
| 12 | DEC |
Days of Week
| Number | Name |
|---|---|
| 0 (or 7) | SUN |
| 1 | MON |
| 2 | TUE |
| 3 | WED |
| 4 | THU |
| 5 | FRI |
| 6 | SAT |
How do cron implementations differ across platforms?
0 and 7 as Sunday for day-of-week. Always check your platform's documentation.How do timezones affect cron schedules?
The schedule 0 9 * * * means "9 AM" — but in which timezone? The answer depends on where the cron daemon runs, not where you wrote the expression. A schedule that fires at 9 AM in your local editor can land at 1 AM in production if the host is set to UTC.
- System cron (Linux): reads the TZ environment variable, otherwise uses
/etc/localtime. Inside Docker, the default is UTC unless the image setsTZor mounts/etc/localtime. - vixie/cronie: supports a
CRON_TZ=Europe/Stockholmline at the top of a crontab to pin the schedule to a named zone. - GitHub Actions: always UTC.
0 9 * * *fires at 09:00 UTC, which is 04:00 in New York during EST. There is no per-workflow timezone option. - AWS EventBridge: historic Rules use UTC only. EventBridge Scheduler (released 2022) accepts a
ScheduleExpressionTimezoneparameter, including DST-aware zones likeAmerica/New_York. - Daylight Saving Time: a job scheduled for 02:30 local can run twice on fall-back day or skip on spring-forward day. UTC sidesteps both.
For workflow-specific tips, see the GitHub Actions cheatsheet.
How do I debug a cron job that doesn't run?
Most failed cron jobs aren't broken cron expressions — they're environment, path, or permission problems. Walk through these checks in order:
- Confirm the entry is installed: run
crontab -las the user that owns the job. System-wide entries live in/etc/crontaband/etc/cron.d/*. - Check cron logs: on Debian/Ubuntu look at
/var/log/syslogfiltered withgrep CRON; on RHEL/CentOS check/var/log/cron; under systemd usejournalctl -u cronorjournalctl -u crond. - Cron has a minimal PATH: usually only
/usr/bin:/bin. Use absolute paths in commands or setPATH=...at the top of the crontab. - Capture stderr: append
>> /var/log/myjob.log 2>&1to the command, or setMAILTO=ops@example.comat the top of the crontab to receive failures by email. - End the line with a newline: entries without a trailing newline are silently ignored on some implementations.
- Validate the expression: paste it into the Cron Expression Parser to see the next 5 fire times. If they don't match what you expected, the bug is in the expression.
- Container caveats: Docker images often ship without a cron daemon, run with PID 1 not forking, and default to UTC. Use a sidecar scheduler or your platform's native scheduler (EventBridge, Cloud Scheduler, Kubernetes CronJob) instead of stuffing cron inside an app container.
References
- crontab(5) — Linux man page — the canonical 5-field syntax, environment variables, and operator semantics.
- AWS EventBridge cron expressions — 6-field format with the trailing year field, UTC default, and EventBridge-specific quirks like the
?wildcard. - GitHub Actions schedule trigger — POSIX 5-field cron, UTC only, with notes on shortest interval (5 minutes) and runner availability.
- Quartz CronTrigger tutorial — the 6/7-field Java/Spring dialect with seconds, year, and the
L W #operators. - crontab.guru — interactive editor that explains any 5-field expression in plain English.
Parse and explain any cron expression with the Cron Expression Parser tool, or grab copy-paste schedules from the Cron examples cheatsheet.