Get started
Documentation

Cron syntax cheat sheet

Five fields, six special characters and a couple of traps everybody falls into. Tables, ready-made expressions and the same thing in systemd format below.

The five crontab fields

┌───────────── 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 Sunday)
│ │ │ │ │
* * * * *  command
Field Range Note
Minute0–59
Hour0–230 is midnight
Day of month1–31the 31st does not exist every month
Month1–12, JAN–DECcase does not matter
Day of week0–7, SUN–SATboth 0 and 7 mean Sunday

Special characters

Character Meaning Example
*any value of the field* * * * * — every minute
,a list0 9,18 * * * — at 9:00 and 18:00
-a range0 9-18 * * * — hourly from 9 to 18
/a step inside the range*/15 * * * * — every 15 minutes
Llast day (not in every cron)0 3 L * * — on the last day of the month
Wnearest weekday (not in every cron)0 3 15W * * — the workday nearest the 15th
#nth weekday of the month (not in every cron)0 3 * * 1#2 — the second Monday

L, W and # are Quartz extensions. The classic Vixie cron shipped with Debian and Ubuntu does not understand them; CronAlive accepts the standard five fields and the shorthands below.

Shorthands

Shorthand Equivalent
@yearly, @annually0 0 1 1 *
@monthly0 0 1 * *
@weekly0 0 * * 0
@daily, @midnight0 0 * * *
@hourly0 * * * *
@rebootonce when the system starts

Common schedules

When Expression
every minute* * * * *
every 5 minutes*/5 * * * *
every 30 minutes0,30 * * * *
hourly at :1515 * * * *
every 2 hours0 */2 * * *
daily at 3:3030 3 * * *
twice a day, 6:00 and 18:000 6,18 * * *
weekdays at 9:000 9 * * 1-5
weekends at 10:000 10 * * 6,0
every Monday at 4:000 4 * * 1
the 1st of the month at 0:000 0 1 * *
every 15 minutes during office hours*/15 9-18 * * 1-5

Common mistakes

A step larger than the range

*/60 * * * * does not mean "once an hour". The step applies inside the field's range: minutes are 0–59, so the only matching value is 0. It will fire at the top of every hour — by accident, not by meaning. The correct form is 0 * * * *. Likewise */70 never fires at all.

Day of month together with day of week

When both fields are set (neither is *), cron combines them with OR, not AND. 0 3 13 * 5 fires on the 13th of every month and on every Friday — not only on Friday the 13th. This behaviour has been baked into Vixie cron from the start; to get AND you have to check the date inside the script.

Sunday as both 0 and 7

Both values are valid, but 1-7 means Monday through Sunday, that is the whole week — not "weekdays". Weekdays are 1-5.

Time zone

Cron runs in the system time zone (or in CRON_TZ if it is set at the top of the crontab). A server on UTC and a schedule you read as local time differ by exactly the offset you forgot. In a CronAlive check the time zone is explicit, daylight saving transitions included.

The percent sign

In a crontab % is a newline, not a character. A line with date +%Y-%m-%d is cut at the first percent. Escape it: \%.

PATH and environment

Cron has a minimal PATH and none of your profile: ~/.bashrc is not read. Use absolute paths — both for your job and for curl.

The same thing in systemd (OnCalendar)

systemd timers are slowly replacing cron. The format is different: day-of-week YYYY-MM-DD HH:MM:SS, where * is any value and / is a step.

When cron OnCalendar
every minute* * * * **-*-* *:*:00
every 5 minutes*/5 * * * **:0/5
hourly0 * * * *hourly
daily at 3:3030 3 * * **-*-* 03:30:00
weekdays at 9:000 9 * * 1-5Mon..Fri 09:00
the 1st at 0:000 0 1 * *monthly

Check an expression and see the next runs:

systemd-analyze calendar 'Mon..Fri 09:00' --iterations=3

Timers have something cron does not: Persistent=true catches up a run missed while the machine was off, and RandomizedDelaySec= spreads simultaneous jobs apart. A unit with pings is in the snippets.

Make sure the job actually runs

A correct expression guarantees nothing: cron may not have reloaded the crontab, the job may die on its first line, the server may reboot. Create a check with the same schedule and you will hear about the silence the same hour: cron job monitoring in 5 minutes.