Cron Expression Examples

Sixty ready-to-copy schedules, from every minute to the last weekday of the quarter

Most of the time you do not need to understand cron from first principles — you need the one line that runs your backup at 3 AM on the first Sunday of the month. This page collects sixty schedules we have actually needed, grouped by how often they fire, with the behaviour worth knowing about each one. Every expression is standard five-field Unix cron unless the table says otherwise, and every one can be pasted into the Explainer to see its next run times.

Every N minutes

Step values in the minute field (*/n) cover almost every sub-hourly schedule. A step divides the whole 0–59 range, so it only lands evenly when n divides 60.

Sub-hourly schedules
ExpressionRunsNotes
* * * * *Every minute1,440 runs a day. The fastest standard cron can go.
*/2 * * * *Every 2 minutesFires on even minutes: :00, :02, :04…
*/5 * * * *Every 5 minutesThe most common polling interval.
*/10 * * * *Every 10 minutes:00, :10, :20, :30, :40, :50.
*/15 * * * *Every 15 minutesFour runs an hour, on the quarter.
*/30 * * * *Every 30 minutesEquivalent to 0,30 * * * *.
*/7 * * * *Every 7 minutes, resetting each hour:00, :07…:56, then :00 again — a 4-minute gap at the hour boundary because 7 does not divide 60.
7 * * * *At 7 minutes past every hourOffsetting off :00 keeps you out of the traffic spike every other job creates.
0,15,30,45 * * * *Every 15 minutesAn explicit list; identical to */15 but clearer to some readers.
*/5 * * * 1-5Every 5 minutes, Monday to FridayNothing at all on Saturday or Sunday.
Watch the step boundary

A step always restarts at the beginning of its field's range, not from the previous run. */7 does not mean "every 7 minutes forever" — it means "every 7th minute of each hour", so the gap between 23:56 and 00:00 is four minutes, not seven. If you need a true fixed interval that does not divide an hour, use a scheduler with interval support rather than cron.

Hourly and every N hours

Put a fixed value in the minute field and a step or range in the hour field. Leaving the minute as * is nearly always a mistake: * */2 * * * runs sixty times in each of those hours, not once.

Hourly schedules
ExpressionRunsNotes
0 * * * *Every hour, on the hour24 runs a day.
30 * * * *Every hour at half pastUseful for staggering against hourly jobs on :00.
0 */2 * * *Every 2 hours00:00, 02:00, 04:00…22:00.
0 */3 * * *Every 3 hoursEight runs a day starting at midnight.
0 */4 * * *Every 4 hours00:00, 04:00, 08:00, 12:00, 16:00, 20:00.
0 */6 * * *Every 6 hoursFour runs a day.
0 */12 * * *Twice a dayMidnight and noon.
0 9-17 * * *Hourly from 09:00 to 17:00Nine runs — the range includes both ends.
0 8-18/2 * * *Every 2 hours between 08:00 and 18:0008:00, 10:00, 12:00, 14:00, 16:00, 18:00. A step applied to a range.
15,45 * * * *Twice an hour, at :15 and :45A list in the minute field.

Daily at a fixed time

Cron uses 24-hour time. There is no AM/PM and no seconds — 0 18 * * * is 6 PM, and it fires at 18:00:00 in the server's time zone, whatever that happens to be.

Once-a-day schedules
ExpressionRunsNotes
0 0 * * *Every day at midnightThe classic nightly job. Equivalent to @daily.
30 2 * * *Every day at 02:30A common backup window — but see the DST warning below.
0 3 * * *Every day at 03:00Safely past the daylight saving transition hour in most zones.
0 6 * * *Every day at 06:00Morning report generation.
0 12 * * *Every day at noon
0 18 * * *Every day at 18:006 PM in 24-hour time.
0 23 * * *Every day at 23:00End-of-day rollup before the date changes.
0 0,12 * * *Twice daily, midnight and noonA list is clearer than */12 when the two times are not evenly spaced.
Avoid the 01:00–03:00 window

In zones that observe daylight saving, a daily job scheduled between roughly 01:00 and 03:00 will be skipped on the spring-forward day, or run twice on the fall-back day, depending on your cron implementation. Scheduling at 0 3 * * * or later sidesteps the whole problem. The time zones and DST guide walks through exactly what each implementation does.

Weekdays, weekends and business hours

Day of week is the fifth field, numbered 0 (Sunday) through 6 (Saturday). Most implementations also accept 7 for Sunday and three-letter names such as MON.

Weekday and weekend schedules
ExpressionRunsNotes
0 9 * * 1-5Weekdays at 09:00Monday through Friday.
0 9 * * MON-FRIWeekdays at 09:00Identical, using names. Names are case-insensitive but less portable than numbers.
0 18 * * 1-5Weekdays at 18:00End-of-workday jobs.
0 0 * * 6,0Weekends at midnightSaturday and Sunday.
0 2 * * 6Saturdays at 02:00Weekly maintenance while nobody is working.
*/15 9-17 * * 1-5Every 15 minutes, 09:00–17:59, weekdays36 runs per weekday. The 17 covers the whole 17:00 hour, so the last run is 17:45.
0 9-17 * * 1-5Hourly during business hours, weekdaysNine runs a day, 45 a week.
*/30 8-18 * * 1-5Every half hour, 08:00–18:59, weekdaysExtend the hour range by one if you want coverage through the end of the day.

Weekly

A weekly schedule is just a daily schedule with the day-of-week field restricted, and the day-of-month field left as *. Restricting both is the single most common cron mistake — see the last section.

Weekly schedules
ExpressionRunsNotes
0 0 * * 0Every Sunday at midnightEquivalent to @weekly.
0 0 * * 1Every Monday at midnightStart-of-week reset.
0 4 * * 0Every Sunday at 04:00Weekly full backup.
0 8 * * 1Every Monday at 08:00Weekly summary email before the day starts.
0 17 * * 5Every Friday at 17:00End-of-week report.
0 12 * * 1,3,5Monday, Wednesday and Friday at noonA list in the day-of-week field.

Monthly

Day of month is the third field, 131. Standard cron has no "last day of month" token, which is why the workarounds below exist.

Monthly schedules
ExpressionRunsNotes
0 0 1 * *Midnight on the 1st of every monthEquivalent to @monthly.
0 3 1 * *03:00 on the 1stMonthly billing or archival run.
0 0 15 * *Midnight on the 15thMid-month.
0 0 1,15 * *1st and 15thTwice-monthly payroll pattern.
0 0 28 * *The 28th of every monthThe last day that exists in every month, February included.
0 0 1 */3 *The 1st of every third monthJanuary, April, July, October.
0 9 1-7 * 1Not "the first Monday"This runs on days 1–7 and on every Monday, because of OR logic. See below for the correct form.
0 0 L * *Last day of the monthQuartz and some extended dialects only. Standard Unix cron rejects L.

Running on the last day of the month in standard cron

Because Unix cron has no L, the portable trick is to run daily and let the command decide whether today is the last day:

0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/month-end.sh

The schedule narrows cron to the only four candidate days, and the shell test lets exactly one of them through. Note the escaped \%: inside a crontab, an unescaped % is turned into a newline and everything after it is fed to the command on standard input.

Running on the first Monday of the month

Same idea — restrict day of month to the first week and day of week to Monday, then guard in the shell so the OR logic cannot fire on the wrong day:

0 9 1-7 * * [ "$(date +\%u)" = "1" ] && /usr/local/bin/first-monday.sh

Only days 1–7 are candidates, and date +%u returns 1 only on Monday, so exactly one day a month qualifies. In Quartz you would write this directly as 0 0 9 ? * MON#1.

Quarterly and yearly

Low-frequency schedules
ExpressionRunsNotes
0 0 1 1,4,7,10 *The 1st of each quarterJanuary, April, July, October — calendar quarters.
0 0 1 2,5,8,11 *Quarters offset by one monthFor fiscal years starting in February.
0 0 1 */6 *Twice a yearJanuary and July.
0 0 1 1 *Midnight on 1 JanuaryEquivalent to @yearly or @annually.
0 0 31 12 *Midnight on 31 DecemberYear-end close.
0 2 1 JAN,APR,JUL,OCT *Quarterly at 02:00Month names, where supported.

Special strings

Most cron implementations accept a handful of shorthand strings in place of all five fields. They are readable and portable across Vixie cron, cronie and systemd's cron compatibility, though not across every scheduler — Kubernetes CronJobs accept them, AWS EventBridge does not.

Cron shorthand strings
StringEquivalentMeaning
@yearly0 0 1 1 *Once a year at midnight, 1 January. @annually is a synonym.
@monthly0 0 1 * *Midnight on the first of the month.
@weekly0 0 * * 0Midnight on Sunday.
@daily0 0 * * *Midnight every day. @midnight is a synonym.
@hourly0 * * * *The top of every hour.
@rebootOnce, when the cron daemon starts after a boot. No time equivalent, and not supported everywhere.

Five examples that do not mean what they look like

These are the expressions that pass review and then behave unexpectedly in production. Each one is syntactically valid, which is why reading the computed run times matters more than reading the syntax.

1. 0 0 13 * 5 — not Friday the 13th

When day of month and day of week are both restricted, standard cron runs when either matches. This fires on the 13th of every month and on every Friday — roughly 16 times a month, not once or twice a year. To get only Friday the 13th, schedule 0 0 13 * * and guard on [ "$(date +\%u)" = "5" ] in the command.

2. * */2 * * * — not every two hours

The minute field is *, so this runs every minute of every second hour: 60 runs at 00:00–00:59, then 60 more at 02:00–02:59, and so on. 720 runs a day. The intended expression is 0 */2 * * *.

3. 0 9-17 * * * — ends at 17:00, not 17:59

This one is correct as written, but the neighbouring case trips people up: */15 9-17 * * * runs through 17:45, because the hour range 9-17 includes the whole of the 17:00 hour. If you want coverage to stop at 17:00 exactly, the minute restriction has to do that work.

4. 0 0 31 * * — silently skips four months

February, April, June, September and November have no 31st, so a job scheduled on the 31st runs seven times a year instead of twelve. Use 28 if you want it every month, or the last-day-of-month pattern above.

5. */90 * * * * — invalid or truncated

A step larger than the field's range is meaningless. Depending on the implementation, cron either rejects the line outright or clamps it to something you did not intend. Cron cannot express "every 90 minutes" at all: the closest honest approximations are 0 */2 * * * or two separate lines such as 0 0,3,6,9,12,15,18,21 * * * plus 30 1,4,7,10,13,16,19,22 * * *.

One page per schedule

Every schedule above also has a dedicated page with live next-run times, usage notes and the specific trap that comes with it — browse them in the schedule reference.

Build your own

If none of these is quite right, compose the schedule field by field in the visual builder and read the next five run times before you commit it — that is the fastest way to catch a wrong schedule while it is still cheap. To decode an expression you inherited from someone else's config file, paste it into the Explainer.