belun.app Blog
RU

Cron Expressions Explained: How to Read a Crontab Schedule

The five cron fields, steps and ranges, the day-of-month/day-of-week gotcha, and a set of schedules you can copy straight into your crontab.

Server room with clock and scheduling display — cron expressions for automated jobs

I have lost more time to a misread cron line than I’d like to admit. The classic: a backup that was supposed to run nightly fired every minute instead, because I put the * in the wrong slot. Five little fields, and one of them in the wrong place quietly torches your evening. The Cron Expression Generator exists so you can check the schedule before it bites you, not after.

The five fields, left to right

A cron line is just five values separated by spaces:

* * * * *
│ │ │ │ │
│ │ │ │ └── day of week (0–6, Sunday is 0)
│ │ │ └──── month (1–12)
│ │ └────── day of month (1–31)
│ └──────── hour (0–23)
└────────── minute (0–59)

A * means “every”. So 30 8 * * 1 reads as: minute 30, hour 8, any day, any month, Monday. That’s 8:30 every Monday. Read it left to right and it stops being cryptic.

Steps, ranges, and lists

Three bits of syntax cover almost everything you’ll write:

  • A range uses a hyphen: 1-5 in the day-of-week field is Monday through Friday.
  • A list uses commas: 0,30 in the minute field means on the hour and on the half hour.
  • A step uses a slash: */15 means every 15th value — minutes 0, 15, 30, 45.

You can combine them. 0-30/10 in minutes gives you 0, 10, 20, 30. And 0 9-17 * * 1-5 is “top of the hour, 9am to 5pm, weekdays” — a fine schedule for a job that should only run during office hours.

The gotcha that gets everyone

Here’s the one that’s genuinely confusing, and it’s not your fault. When both the day-of-month and day-of-week fields are set to something other than *, cron treats them as OR, not AND.

Take 0 0 13 * 5. You might read that as “midnight on Friday the 13th”. It actually runs at midnight on the 13th of every month and every single Friday. Two separate triggers, unioned together. This behavior goes back to the original Vixie cron and it’s documented in the man page, but almost nobody reads the man page until something has already gone wrong. The generator follows this rule when it lists run times, so you’ll see the real schedule instead of the one you assumed.

Schedules worth memorizing

A few that come up constantly:

  • */5 * * * * — every 5 minutes, the workhorse for health checks
  • 0 * * * * — once an hour, on the hour
  • 0 3 * * * — 3am daily, a quiet window for backups
  • 0 0 * * 0 — midnight every Sunday
  • 0 0 1 * * — midnight on the 1st of each month

Most systems also accept shorthand macros. @daily, @hourly, @weekly, and friends expand to the equivalent five-field line, and @reboot runs once when the machine starts. They’re easier to read at a glance, though plain fields give you finer control.

A note on timezones

Cron runs against the system clock of whatever machine it lives on. A server in UTC and your laptop in Berlin will disagree about when 0 9 * * * happens. The generator shows the next runs in your browser’s local time, which is great for sanity-checking the pattern — just remember to map it back to your server’s timezone before you trust it in production.

Paste your line into the Cron Expression Generator, read the sentence it gives you, and glance at the next five runs. If the sentence matches what you meant, ship it.

Try the tool

Cron Expression Generator →