Overview
A cron expression has five fields: minute, hour, day of month, month, day of week. The grammar also appears in crontab, GitHub Actions, and Kubernetes CronJobs; Quartz, Spring, and AWS EventBridge rules use variants with a different field count.
Fields
Write times in the scheduler’s timezone, and check the field count for your engine.
| Field | Range | Notes |
|---|---|---|
| Minute | 0-59 | |
| Hour | 0-23 | System timezone for crontab; UTC on most hosted schedulers. |
| Day of month | 1-31 | |
| Month | 1-12 or JAN-DEC | |
| Day of week | 0-6 or SUN-SAT | 0 is Sunday; many implementations also accept 7. |
Variants: Quartz and Spring put seconds first (and Quartz allows a year last). AWS EventBridge rules use six fields (minute, hour, day of month, month, day of week, year) and require ? in one of the two day fields.
Special characters
Use only characters your engine supports; L, W, #, and ? are not standard cron.
| Char | Meaning | Example |
|---|---|---|
* | Every value | * * * * * every minute |
, | List | 0 9,17 * * * at 09:00 and 17:00 |
- | Range | 0 9-17 * * * hourly, 09:00 to 17:00 |
/ | Step | */15 * * * * every 15 minutes |
L W # ? | Last, nearest weekday, nth weekday, no value | Quartz and EventBridge only. |
Common schedules
Copy a schedule, then verify the next run times before deploying.
| Expression | Runs |
|---|---|
0 * * * * | Every hour, on the hour |
0 9 * * 1-5 | Weekdays at 09:00 |
0 0 1 * * | Midnight on the 1st of each month |
*/15 9-17 * * 1-5 | Every 15 minutes during weekday business hours |
0 0,12 * * * | Midnight and noon |
0 8-20/2 * * * | Every 2 hours from 08:00 to 20:00 |
@reboot | At startup (cron daemons only) |
@hourly @daily @weekly @monthly @yearly | Same as 0 * * * *, 0 0 * * *, 0 0 * * 0, 0 0 1 * *, 0 0 1 1 * |
Timezones
Pin the timezone explicitly; never assume local time.
| System | Default | How to set |
|---|---|---|
| cronie (Fedora, RHEL, Arch) | System zone | CRON_TZ=America/New_York in the crontab. |
Debian and Ubuntu cron | System zone | CRON_TZ is not documented; convert to the system zone or use a systemd timer. |
| GitHub Actions | UTC | timezone: "America/New_York" next to cron: in the schedule entry. |
| Kubernetes CronJob | Controller zone | spec.timeZone: "America/New_York" (stable since 1.27). |
| AWS EventBridge rule | UTC | Use EventBridge Scheduler for a timezone. |
Around daylight saving changes, cronie skips non-existent times and runs ambiguous times twice.
Operate
Guard long jobs against overlap and keep their output out of local mail.
| Command | Use |
|---|---|
crontab -l / crontab -e | List / edit your crontab. |
journalctl -u cron or /var/log/syslog | Execution log (unit is crond on RHEL-family). |
flock -n /tmp/job.lock cmd | Skip a run while the previous one is still going. |
MAILTO="" | Stop cron mailing job output (or redirect it: >/dev/null 2>&1). |
Gotchas
Avoid these; each makes a job run at the wrong time or not at all.
| Gotcha | Fix |
|---|---|
When day of month and day of week are both restricted, cron runs when either matches. 0 0 1 * 1 fires on the 1st and on every Monday. | Schedule daily and test the other condition in the script. |
*/7 in the minute field means 0, 7, …, 56, then restarts at 0 next hour. | Use a step that divides 60. |
| Cron runs with a minimal environment and no login profile. | Use absolute paths and set PATH at the top. |
% in a command is turned into a newline. | Escape it as \%. |
| GitHub Actions schedules run on the default branch, at most every 5 minutes, and may start late at the top of the hour. | Offset the minute (17 * * * *). |
| Scheduled workflows in public repos are disabled after 60 days without repository activity. | Re-enable them or push a commit. |