What Is a Cron Expression?
If you've ever set up a server, a scheduled backup, or an automated email, you've probably encountered cron. Cron is a time-based job scheduler in Unix-like operating systems. It allows you to run scripts and commands automatically at specified intervals — every minute, every Tuesday at 3am, on the first day of every month. The key to cron is the expression that defines when a job should run.
A cron expression is a compact string made up of five fields that together specify the exact timing of your scheduled task. Think of it as a tiny programming language for time. Once you understand the grammar, you can read any cron expression at a glance and build complex schedules without writing a single line of Python or Bash.
The Five-Field Format
Every cron expression has five fields, separated by spaces. They represent, from left to right: minute, hour, day of month, month, and day of week.
┌───────────── minute (0-59) │ ┌───────────── hour (0-23) │ │ ┌───────────── day of month (1-31) │ │ │ ┌───────────── month (1-12) │ │ │ │ ┌───────────── day of week (0-6, Sunday=0) │ │ │ │ │ * * * * *
Each field accepts specific values. The most flexible is the asterisk (*), which means "every possible value." So * * * * * means "every minute of every hour of every day of every month" — essentially, run continuously.
Common Cron Expression Examples
Let's build up from simple to more nuanced schedules:
0 * * * *— Every hour, at minute 0 (so 1:00, 2:00, 3:00...)0 0 * * *— Every day at midnight30 9 * * 1-5— Weekdays at 9:30am0 0 1 * *— First day of every month at midnight*/15 * * * *— Every 15 minutes0 3 * * 0— Every Sunday at 3:00am0 6,18 * * *— Every day at 6:00am and 6:00pm
Special Characters That Give You More Control
Beyond simple values, cron supports special characters that let you express ranges, steps, and complex patterns:
Slash (/) — Used for steps. */5 means "every 5 units." So */5 * * * * runs every 5 minutes. 0 */2 * * * runs every 2 hours.
Hyphen (-) — Defines a range. 9-17 in the hour field means "between 9am and 5pm." So 0 9-17 * * 1-5 runs every hour from 9 to 5 on weekdays.
Comma (,) — Lists specific values. 0 8,12,18 * * * runs at 8am, noon, and 6pm every day.
Question mark (?) — Used in the day-of-month and day-of-week fields when you want to specify one but not the other. Since these two fields can conflict, the ? lets you say "I don't care about this field."
Timezone Considerations
One of the most common gotchas with cron is timezone. By default, cron runs in the server's local timezone, which may not be where your users are — or where you are. If you schedule a job for "3am" but your server is in UTC and you're in New York (UTC-5), the job actually runs at 3am UTC, which is 10pm the previous day in New York time.
Modern cron systems and cloud platforms often let you specify a timezone directly. For example, in systemd timers or AWS EventBridge, you can write Cron(0 9 ? * Mon-Fri *) with an explicit timezone like America/New_York. Always verify which timezone your cron daemon is actually using.
Testing Your Cron Expression
Before you deploy a cron job, test your expression. Online cron validators let you paste an expression and see the next 10 execution times. This catches mistakes like scheduling a daily job for 25:00 (invalid) or a monthly job on the 31st when some months only have 28 days.
Also check the cron daemon logs on your server. Most systems log cron executions to /var/log/syslog or /var/log/cron. If a job isn't running, this is the first place to look.
Troubleshooting Common Problems
If your cron job isn't running, work through this checklist: Is the cron service actually running? Does the command work when run manually? Are file paths relative or absolute — remember cron runs with a minimal environment, so relative paths often break. Does your script have execute permissions? And critically, is the cron expression actually matching the time you think it is?
Another common issue: environment variables. Your interactive shell might have PATH set to include /usr/local/bin, but cron starts with a stripped-down environment. Always use absolute paths in cron commands.
Wrapping Up
Cron expressions are one of those tools that look intimidating at first but become second nature quickly. Once you've set a few schedules and seen them fire on time, the five-field syntax starts to feel natural. A good cron expression generator takes the guesswork out of the syntax and shows you exactly when your job will run — no more late-night server checks wondering why your backup didn't fire.