Cron syntax
A cron expression is five fields separated by spaces, read left to right:
┌───────────── minute 0–59
│ ┌─────────── hour 0–23
│ │ ┌───────── day of month 1–31
│ │ │ ┌─────── month 1–12 or JAN–DEC
│ │ │ │ ┌───── day of week 0–7 or SUN–SAT (0 and 7 are both Sunday)
│ │ │ │ │
* * * * * command
| Syntax | Meaning | Example |
|---|---|---|
* | Every value | * * * * * every minute |
5 | Exactly this value | 0 5 * * * at 05:00 |
1-5 | Range, inclusive | 0 9 * * 1-5 09:00 Monday to Friday |
1,15 | List | 0 0 1,15 * * midnight on the 1st and 15th |
*/10 | Step: every 10th value starting from the minimum | */10 * * * * every 10 minutes |
8-18/2 | Step within a range | 0 8-18/2 * * * 08:00, 10:00 … 18:00 |
@daily | Macro: @yearly @monthly @weekly @daily @hourly (and @reboot in crontab, not a schedule) | @weekly = 0 0 * * 0 |
Day of month and day of week together
This is the rule that surprises most people. When both the day-of-month and the day-of-week fields are restricted (neither is *), traditional cron runs the job when either matches, not both. 0 0 13 * 5 runs on every 13th and on every Friday, not only on Friday the 13th. There is no standard way to express “Friday the 13th” in five fields; put the test in the command instead:
0 0 13 * * [ "$(date +\%u)" = 5 ] && /path/to/job
Note the escaped \%: in a crontab file, an unescaped percent sign is converted to a newline.
Timezone
Classic cron runs in the system's local timezone (or the TZ or CRON_TZ variable set in the crontab). A job scheduled for 02:30 may run twice or not at all on daylight-saving transition days. Container schedulers and cloud services often default to UTC. The next-run list above can be switched between your browser's local zone and UTC; pick the one your scheduler uses.
Cron flavours
The 5-field syntax here is the POSIX / Vixie cron used by Linux crontab, macOS, Kubernetes CronJobs, GitHub Actions schedule, and most hosted schedulers. Some systems extend it:
- Quartz (Java, Spring, AWS EventBridge) uses 6 or 7 fields with seconds first,
?for “no specific value”, andL,W,#modifiers. Its day-of-week numbering starts at 1 = Sunday. - Jenkins adds
Hfor a hashed, spread-out value. - systemd timers use a different calendar syntax entirely (
OnCalendar=Mon..Fri 09:00).
Expressions in those dialects are reported here as invalid with a note saying which feature is not standard.
Common mistakes
* 9 * * *runs every minute from 09:00 to 09:59. For once at nine, write0 9 * * *.*/90 * * * *does not mean every 90 minutes; steps do not carry across fields. Use two lines or a different scheduler.0 0 31 * *only runs in months with 31 days.0 0 31 2 *never runs.- Cron uses a minimal
PATHand no login shell. Use absolute paths and set variables at the top of the crontab. - Output is mailed to the user by default; redirect it (
>> /var/log/job.log 2>&1) or setMAILTO="".
Editing a crontab
crontab -e # edit your crontab
crontab -l # list it
# system-wide: /etc/crontab and /etc/cron.d/* have an extra "user" field before the command
To build an expression from a form rather than write it by hand, use the Cron Expression Builder.