ToolSite

Cron Syntax for Beginners: How to Build a Schedule

Cron syntax explained in plain terms. Learn the five fields, special characters, and common schedules. Build cron expressions with our free generator tool.

By ToolSite6 min readguides

What Cron Is

Cron is a time-based job scheduler built into Unix-like operating systems. It runs commands on a repeating schedule defined by a simple five-field expression. Every developer touches cron eventually: database backups, log rotation, cache clearing, email reports, and certificate renewal all depend on it.

The name comes from "chronos," the Greek word for time. The cron daemon (crond) wakes up every minute, checks all crontab files for jobs scheduled at the current minute, and runs them. It's been in Unix since Version 7 (1979) and is still the standard scheduler on Linux and macOS.

The Five Fields

A cron expression has five space-separated fields:

*    *    *    *    *
│    │    │    │    │
│    │    │    │    └── day of week (0-7, 0 and 7 = Sunday)
│    │    │    └─────── month (1-12)
│    │    └──────────── day of month (1-31)
│    └───────────────── hour (0-23)
└────────────────────── minute (0-59)

Each field accepts a number, a wildcard (*), or a combination of operators. The fields are read left to right from the smallest unit of time (minute) to the widest (day of week/month).

Operators

| Operator | Meaning | Example | |---|---|---| | * | Every value | * * * * * = every minute | | , | List of values | 0,30 * * * * = at minutes 0 and 30 | | - | Range of values | 1-5 * * * * = minutes 1 through 5 | | / | Step values | */15 * * * * = every 15 minutes | | L | Last (non-standard) | Some schedulers support L for last day |

The * wildcard means "every possible value for this field." In the minute field, * means every minute (0 through 59). In the hour field, * means every hour (0 through 23).

The / step operator divides the field's range. */5 in the minute field means "every 5th minute": 0, 5, 10, 15, 20, ..., 55. It starts at the first value of the range (0), not "every 5 minutes from now."

Common Schedules

| Expression | Meaning | |---|---| | * * * * * | Every minute | | 0 * * * * | Every hour at minute 0 | | 0 0 * * * | Daily at midnight | | 0 0 * * 0 | Weekly at midnight Sunday | | 0 0 1 * * | Monthly on the 1st at midnight | | 0 0 1 1 * | Yearly on January 1st at midnight | | */5 * * * * | Every 5 minutes | | 0 */2 * * * | Every 2 hours | | 30 4 * * 1-5 | 4:30 AM on weekdays | | 0,30 * * * * | At minutes 0 and 30 |

The "Every 5 Minutes" Trap

*/5 * * * * runs at 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55. That's 12 times per hour. It does not run at 1, 2, 3, 4. This is correct for most use cases but worth double-checking when precision matters.

If you need exactly "every 5 minutes starting now," cron can't do it directly. The */5 always starts from 0. To offset, use a list: 3,8,13,18,23,28,... (every 5 minutes starting at minute 3). That's tedious to type but sometimes necessary for staggering jobs across multiple servers.

Day-of-Week and Day-of-Month Interaction

When both day-of-month and day-of-week are specified (neither is *), the job runs when EITHER field matches. This is the "OR" rule:

0 0 1 * 1    Runs on the 1st of the month AND every Monday
0 0 * * 1    Runs only on Mondays (day-of-month is *)
0 0 1 * *    Runs only on the 1st (day-of-week is *)

If you need "the 1st of the month only if it's a Monday," cron doesn't support that directly. Add the logic inside the script. Check the date at the start of the job and exit early if the condition isn't met.

How to Build and Verify a Cron Expression

  1. Start with what you want: "every weekday at 9 AM."
  2. Break it down: minute = 0, hour = 9, day-of-month = *, month = *, day-of-week = 1-5.
  3. Build the expression: 0 9 * * 1-5.
  4. Verify with a Cron Generator that translates the expression back to human-readable English.

The Cron Generator works both directions: enter a cron expression and see the human-readable description, or build a schedule from dropdowns and get the cron expression. This is the fastest way to catch off-by-one errors in day-of-week or to verify that */15 in the hour field behaves as you expect.

Never trust a cron expression you wrote from memory. Always verify. A typo that changes 0 0 * * 0 (weekly) to * 0 * * 0 (every minute for one hour once a week) can send thousands of emails or fill a disk with log entries.

Cron in Practice

Cron expressions appear in:

  • Linux crontab: crontab -e to edit user-level cron jobs. System-wide jobs go in /etc/crontab or /etc/cron.d/.
  • GitHub Actions: on: schedule: - cron: "0 0 * * *" using POSIX cron syntax (5 fields). GitHub runs on a best-effort schedule during high load.
  • GitLab CI: schedule keyword in .gitlab-ci.yml with the pipeline schedules feature.
  • Kubernetes CronJobs: schedule field in the CronJob spec. Supports seconds as an optional sixth field in some distributions.
  • Vercel cron jobs: vercel.json crons array. Supports 5-field expressions with some limitations on minimum frequency.

Each platform uses the same five-field syntax with minor variations. GitHub Actions runs cron jobs at the scheduled minute plus a delay of up to several minutes during busy periods. Kubernetes CronJobs are more punctual but can overlap if a job takes longer than its interval (use concurrencyPolicy to control this). Always read the platform's cron documentation for quirks.

Crontab Syntax for the Terminal

To edit your crontab:

crontab -e    # Edit your user crontab
crontab -l    # List your current cron jobs
crontab -r    # Remove your crontab (careful!)

A crontab line looks like:

# ┌─ minute (0-59)
# │ ┌─ hour (0-23)
# │ │ ┌─ day of month (1-31)
# │ │ │ ┌─ month (1-12)
# │ │ │ │ ┌─ day of week (0-7, 0/7 = Sunday)
# │ │ │ │ │
  * * * * * command to run

Each user has their own crontab. Root's crontab can run commands as any user.

Try it yourself: open the Cron Generator. Build a schedule for "every Monday at 3:30 AM" using the dropdowns. The tool outputs 30 3 * * 1. Then enter */10 9-17 * * 1-5 and read the human-readable description: "Every 10 minutes, between 9:00 AM and 5:59 PM, Monday through Friday."

Related Reading