Cron Syntax Explained

A cron expression is five fields separated by spaces: minute, hour, day of month, month and day of week. Each field takes a number, a * for every value, a range like 1-5, a list like 1,15 or a step like */10. So 0 9 * * 1-5 means 09:00 on weekdays, and */15 * * * * means every 15 minutes.

The five fields

PositionFieldAllowed values
1Minute0–59
2Hour0–23
3Day of month1–31
4Month1–12 or JAN–DEC
5Day of week0–6 or SUN–SAT (7 is also Sunday)

Special characters

  • * every value. * * * * * runs every minute.
  • , a list. 0 8,20 * * * runs at 08:00 and 20:00.
  • - a range. 0 9-17 * * * runs on the hour from 09:00 to 17:00.
  • / a step. */20 * * * * runs at minutes 0, 20 and 40. 5/20 runs at 5, 25 and 45.

Steps count from the start of the range, not from when you saved the job. */7 in the minute field runs at 0, 7, 14 … 56, then again at 0, so the gap across the hour is 4 minutes, not 7.

Examples

ExpressionRuns
*/5 * * * *Every 5 minutes
0 * * * *Every hour, on the hour
0 0 * * *Every day at midnight
30 6 * * 1-5Weekdays at 06:30
0 0 * * 0Every Sunday at midnight
0 0 1 * *The 1st of every month at midnight
0 0 1 1 *Once a year, on 1 January
15 14 1 */3 *14:15 on the 1st of every third month (Jan, Apr, Jul, Oct)

Paste any of these into the cron explainer to see the next run times.

The day-of-month and day-of-week trap

When both day fields are set to something other than *, cron runs the job if either matches. 0 0 13 * 5 does not mean Friday the 13th; it means every 13th of the month and every Friday. To get Friday the 13th, schedule on the 13th and check the weekday inside the job.

Time zones

A crontab on a Linux server uses the server's time zone. GitHub Actions schedules, Cloudflare Cron Triggers and AWS EventBridge cron expressions run in UTC. If a job "runs an hour late" after a clock change, the schedule is almost certainly in a different time zone from the one you had in mind.

Shortcuts

Most cron implementations accept @hourly, @daily (or @midnight), @weekly, @monthly, @yearly and @reboot, which runs once at startup.

Frequently asked questions

How do I run a cron job every 30 seconds?

Standard cron cannot go below one minute. Either run a job every minute that does its work twice with a 30-second sleep, or use a scheduler that supports seconds, such as a systemd timer or a Quartz-style scheduler.

How do I run a job on the last day of the month?

Standard cron has no "last day" symbol (L is a Quartz extension). A common trick is to run on days 28–31 and check in the command whether tomorrow is the 1st: 0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && ./job.sh

Why did my cron job not run?

The usual causes are a different time zone from the one you expected, a PATH that does not include your program (cron runs with a minimal environment), an unescaped % sign in the command (cron treats % as a newline), or both day fields set so the schedule means something else.

Tools for this guide