Skip to content
Cron Cookbook

Cron and crontab syntax, explained

Cron syntax is five fields, minute, hour, day of month, month and day of week, that tell a scheduler when to run a job. In the crontab format, each line is those five fields followed by the command. Paste an expression to see what it does, or copy a ready-made schedule below.

The five fields

in order, left to right
#FieldAllowed values
1Minute0-59
2Hour0-23
3Day of month1-31
4Month1-12 or JAN-DEC
5Day of week0-6 or SUN-SAT

Special characters

CharacterMeaningExampleRuns
*Every value of the field* * * * *Every minute
,A list of values0 9,17 * * *At 9:00 and 17:00 every day
-A range of values0 9 * * 1-5At 9:00, Monday to Friday
/A step through a range*/15 * * * *Every 15 minutes (:00, :15, :30, :45)

Shortcuts such as @daily and @reboot replace all five fields. Run a job at startup with @reboot. To schedule a PHP script, see how to run PHP as a cron job, and to add or change jobs, how to edit crontab.

Day of month and day of week combine with OR

When both are restricted, standard cron runs the job when either one matches. 0 0 13 * 5 runs at midnight on the 13th of every month and on every Friday, not only on Friday the 13th.

Crontab format: one job per line

A crontab is a plain text file with one job per line: the five schedule fields, then the command to run. Everything after the fifth field, to the end of the line, is the command. Cron also reads comment lines, blank lines and variable settings, so a typical crontab looks like this:

crontab -e
# Variables apply to the jobs below them
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=ops@example.com

# m h dom mon dow command
*/5 * * * * /usr/local/bin/check-queue
30 2 * * 0 /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
@reboot /usr/local/bin/start-worker
LineWhat cron does with it
# commentIgnored. The # has to start the line; after a command it is passed to the shell
NAME=valueSets an environment variable for the jobs below it
m h dom mon dow commandA job: five schedule fields, then the command, separated by spaces or tabs
@daily commandA shortcut such as @hourly, @daily or @reboot in place of the five fields
m h dom mon dow user commandA job in /etc/crontab or /etc/cron.d/, which names the user to run as
VariableMeaning
SHELLThe shell that runs each command. Default /bin/sh
PATHWhere commands are looked up. Default /usr/bin:/bin, so use full paths or set it
MAILTOWho gets each job's output by email. Default the crontab's owner; MAILTO="" sends none
HOMEThe working directory for commands. Default the owner's home directory

The last line needs a line break after it, or crontab refuses the file with “new crontab file is missing newline before EOF”. To install or change a crontab, see how to edit crontab.

Days of the week in cron

The fifth field is the day of the week. Cron counts from Sunday as 0, so Monday is 1 and Saturday is 6, and most crons also accept 7 for Sunday. Three-letter names work too, in any case: MON-FRI is the same as 1-5.

DayNumberNameAWS and Quartz
Sunday0 or 7SUN1
Monday1MON2
Tuesday2TUE3
Wednesday3WED4
Thursday4THU5
Friday5FRI6
Saturday6SAT7
ExpressionRuns
0 9 * * 1-5At 09:00, Monday through Friday (weekdays)
0 10 * * 0,6At 10:00 on Saturday and Sunday (weekends)
0 9 * * 1,3,5At 09:00 on Monday, Wednesday and Friday
30 8 * * 1At 08:30 every Monday
0 0 * * 0At midnight every Sunday

GitHub Actions, Kubernetes and Vercel document the day of week as 0-6, so write Sunday as 0 there, and Vercel doesn't accept names. AWS EventBridge and Quartz number the days 1-7 starting on Sunday, so weekdays are 2-6 or MON-FRI, and the other day field has to be ?.

Run a cron job on a specific date

A date goes in the third and fourth fields: the day of the month (1-31), then the month (1-12, or JAN to DEC). So 0 9 25 12 * runs at 09:00 on 25 December. Leave the day of the week as *.

ExpressionRuns
0 9 25 12 *At 09:00 on the 25th of December, every year
0 9 25 DEC *The same: months take three-letter names
30 6 15 * *At 06:30 on the 15th of every month
0 0 1,15 * *At 00:00 on the 1st and 15th of every month
0 0 1 1,4,7,10 *At 00:00 on the 1st of January, April, July and October
0 0 29 2 *At 00:00 on 29 February, so only in leap years

Cron has no year field, so a date repeats every year. For a job that runs once, use at instead: echo /usr/local/bin/send-report | at 09:00 2026-12-25. A date that never comes, such as 0 0 31 2 *, is accepted but never runs, and 0 0 31 * * skips every month with 30 days or fewer.

Filling in both day fields doesn't narrow the date: cron runs when either one matches, so 0 9 13 * 5 runs on every 13th and on every Friday. For Friday the 13th, or for the last day of the month, which no field can express, schedule the possible days and let date decide in the command. Its % signs need a backslash, as the next section explains.

crontab -e
# Friday the 13th: run on every 13th, then test the weekday
0 9 13 * * [ "$(date +\%u)" = 5 ] && /usr/local/bin/friday-13th

# Last day of the month: run on the 28th-31st, then test tomorrow
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = 01 ] && /usr/local/bin/month-end

date -d tomorrow is GNU date, as on Linux. In AWS EventBridge and Quartz, L in the day-of-month field means the last day, and 6#2 in the day of week means its second Friday.

Dates in a cron command: escape %

Cron treats % in the command part of a crontab line as a newline, and sends everything after the first one to the command as input. So date +%F, which works in a terminal, breaks in crontab: write each % as \%. Cron removes the backslash before it runs the command. The five schedule fields never contain %, so this only affects the command.

crontab -e
# Back up /var/www to a file named by date, such as site-2026-10-13.tgz
0 2 * * * tar -czf /backups/site-$(date +\%F).tgz /var/www
In crontabPrints
date +\%F2026-10-13
date +\%Y\%m\%d20261013
date +\%Y-\%m-\%d_\%H\%M2026-10-13_0200
date +\%s1791856800 (seconds since 1970, UTC)

The date comes from the time zone cron runs in, usually the server's. To check a line before it runs, see how to edit crontab.

Cron cheat sheet: common schedules

Copy the expression for the schedule you need. Each card opens a page with the expression explained and the syntax for crontab, GitHub Actions, Kubernetes, AWS and Vercel.

ExpressionRuns
*/20 * * * *Every 20 minutes
0 */6 * * *Every 6 hours, at 00:00, 06:00, 12:00 and 18:00
0 9,17 * * *At 09:00 and 17:00 every day
0 12 * * 1-5At 12:00, Monday through Friday
0 9-17 * * 1-5Every hour from 09:00 through 17:00, Monday through Friday
0 0 * * 0,6At midnight on Saturday and Sunday
0 0 1 */3 *At midnight on the 1st of January, April, July and October
0 0 1 1 *At midnight on 1 January
ShortcutSame asRuns
@hourly0 * * * *At the start of every hour
@daily0 0 * * *Every day at midnight (also @midnight)
@weekly0 0 * * 0Every Sunday at midnight
@monthly0 0 1 * *At midnight on the 1st of every month
@yearly0 0 1 1 *At midnight on 1 January (also @annually)
@reboot–Once, when cron starts after a boot

Shortcuts work in Linux crontab and Kubernetes CronJobs. GitHub Actions, AWS EventBridge and Vercel take only the five fields, and Jenkins reads @daily as once a day at a time it picks per job. For @reboot, see how to run a cron job at startup, and to check any other expression, paste it into the cron expression validator.