nicetool.dev logo
#cron#devops#linux

Reading and Writing Cron Schedules: 20 Real Examples and 5 Common Traps

Learn the five fields of a cron expression, special characters like *, /, - and comma, common schedules, and the pitfalls that make cron jobs run at the wrong time.

4 min read

Cron is the classic Unix job scheduler, and its syntax has spread far beyond Linux servers: Kubernetes CronJobs, GitHub Actions, AWS EventBridge, Vercel cron, Laravel and Node schedulers all use the same (or very similar) expressions. Yet */15 9-17 * * 1-5 still looks cryptic to many developers. This guide explains the syntax step by step.

The five fields

A standard cron expression has five fields separated by spaces:

┌───────────── 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 to run

A job runs whenever all fields match the current time (with one exception about days, explained below).

Special characters

Symbol Meaning Example Reads as
* Any value * * * * * Every minute
, List 0 9,18 * * * At 09:00 and 18:00
- Range 0 9-17 * * * Every hour from 09:00 to 17:00
/ Step */10 * * * * Every 10 minutes

You can combine them: 0-30/10 means minutes 0, 10, 20 and 30.

20 common schedules

Expression Meaning
* * * * * Every minute
*/5 * * * * Every 5 minutes
*/15 * * * * Every 15 minutes
0 * * * * Every hour, on the hour
30 * * * * Every hour at minute 30
0 */2 * * * Every 2 hours
0 0 * * * Every day at midnight
0 2 * * * Every day at 02:00 (good for backups)
0 9 * * 1-5 Weekdays at 09:00
*/15 9-17 * * 1-5 Every 15 minutes during office hours on weekdays
0 18 * * 5 Every Friday at 18:00
0 0 * * 0 Every Sunday at midnight
0 0 * * 6,0 Saturday and Sunday at midnight
0 0 1 * * First day of every month
0 0 15 * * 15th of every month
0 0 1 1 * Once a year, on January 1st
0 0 1 */3 * First day of every quarter
0 8 1-7 * 1 Careful! See the day-of-month section below
5 4 * * sun Sundays at 04:05
@daily Macro for 0 0 * * *

Many implementations also support the macros @yearly, @monthly, @weekly, @daily and @hourly, and Vixie cron adds @reboot.

To check any expression, paste it into our Cron Expression Parser. It explains every field in plain language and lists the next ten run times in your local time zone or UTC.

When both day fields are set: the OR rule

This is the most misunderstood rule in cron. When both the day-of-month and the day-of-week fields are restricted (neither is *), classic cron runs the job when either of them matches, not both.

0 8 1-7 * 1

Many people read this as "at 08:00 on the first Monday of the month". In reality it runs at 08:00 on days 1 to 7 of every month, and also on every Monday. That is roughly 11 runs per month instead of one.

To run only on the first Monday, keep the day-of-week check in your script:

0 8 1-7 * * [ "$(date +\%u)" = 1 ] && /path/to/job.sh

(Note the escaped %: in a crontab, an unescaped % is treated as a newline.)

Time zones

Cron evaluates expressions in the time zone of the machine or service, and that is often not your local time:

  • Linux cron uses the server's system time zone (frequently UTC on cloud servers).
  • GitHub Actions schedules always run in UTC.
  • Kubernetes CronJobs use the controller's time zone unless you set spec.timeZone (for example Asia/Ho_Chi_Minh).
  • Daylight saving time changes can make a job run twice or be skipped around the switch if the zone uses DST.

If a job must run at 09:00 in Vietnam (UTC+7) on a UTC server, the expression is 0 2 * * *. Our Unix Timestamp Converter is handy for double-checking offsets.

Other pitfalls

  1. Steps restart every hour/day. */7 * * * * runs at minutes 0, 7, 14 … 56 and then again at 0. The gap between 56 and 0 is only 4 minutes.
  2. Invalid dates are skipped. 0 0 31 * * only runs in months with 31 days, and 0 0 29 2 * only in leap years.
  3. Overlapping runs. If a job takes longer than its interval, two copies may run at once. Use a lock (flock), or concurrencyPolicy: Forbid in Kubernetes.
  4. Minimal environment. Cron runs with a small PATH and no shell profile. Use absolute paths and log output: >> /var/log/job.log 2>&1.
  5. Six-field variants. Quartz (Java) and some libraries add a seconds field at the start and use ? for "no specific value". Always check which dialect your platform expects.

Conclusion

Cron syntax is compact but powerful once you know the five fields and four special characters. Remember the OR rule for day-of-month and day-of-week, always confirm the time zone, and test your expression before deploying. Our free Cron Expression Parser shows exactly when a schedule will fire, with no sign-up and no data leaving your browser.

Written by

Nguyễn Thành Nam

Full-Stack Engineer · Backend & Platform

Full-stack engineer with 9+ years of experience building high-traffic APIs and platforms with Go, NestJS, PHP (Laravel, Phalcon) and Node.js. Specializes in GraphQL API design, real-time systems and performance optimization, and builds NICETOOL.dev for the developer community.

Try it yourself

Related articles