code mascot
code7 min read

Cron Syntax: How Unix Schedules Repeating Jobs

Every minute, invisible automation jobs fire across the internet: backups run, reports get generated, stale data is cleaned, and batch pipelines move one step forward. Most of these recurring tasks still rely on one of Unix's oldest tools: cron. If cron expressions look like cryptic punctuation, that's normal. The language is tiny but dense.

Once you learn the grammar, cron becomes predictable and powerful. This guide explains where cron came from, how its five fields work, what each special character means, and what can go wrong when real-world clocks, timezones, and daylight saving time get involved.


Where Cron Came From

Cron emerged in the Unix ecosystem around the Unix V7 era in 1979. Early administrators needed a way to run commands automatically at set times without babysitting terminals. The daemon process, eventually standardized as crond, solved that by periodically checking a table of schedules and launching matching commands.

The design proved remarkably durable. Today, Linux machines, CI/CD platforms, container orchestration systems, and cloud schedulers all expose cron syntax or a close variant. Technology stacks changed. The scheduling language mostly did not.

Key insight: Cron survived because it separates intent from implementation. You declare when a task should run; the scheduler handles the waiting and dispatch.

The Classic 5-Field Cron Format

Standard Unix cron expressions use five time fields followed by a command:

minute hour day-of-month month day-of-week command
  • Minute: 0-59
  • Hour: 0-23
  • Day of month: 1-31
  • Month: 1-12 (or JAN-DEC on many systems)
  • Day of week: 0-7 (Sunday is usually 0 or 7)

Example:

0 9 * * 1-5 /usr/local/bin/send-report

Read it as: run at 09:00 on weekdays. Minute = 0, hour = 9, any day-of-month, any month, day-of-week = Monday through Friday.

How cron matching works

Every minute, crond compares the current timestamp against each field. If the expression matches, it launches the command. Exact day-of-month/day-of-week matching semantics can differ slightly between cron implementations, so production schedules should be validated using your target environment.


Special Characters: *, /, -, and Commas

Most cron patterns are combinations of four operators. Understanding them unlocks most real schedules.

  1. Asterisk * means “every value” for that field.
    0 * * * *   # every hour at minute 0
  2. Slash / defines a step interval.
    */15 * * * * # every 15 minutes
  3. Dash - defines an inclusive range.
    0 9-17 * * 1-5 # 9:00 through 17:00 on weekdays
  4. Comma separates explicit values.
    0 8,12,18 * * * # 08:00, 12:00, and 18:00 daily

These operators can be layered. For example, 0 */2 * * 1-5 means every two hours on weekdays, always at minute zero.

Shortcut aliases

Many cron environments provide nicknames for common schedules. Typical examples include:

  • @yearly0 0 1 1 *
  • @daily0 0 * * *
  • @hourly0 * * * *

Aliases are convenient, but support varies. For portable automation, explicit five-field expressions are usually safer.


How the crond Daemon Executes Jobs

Cron is not a shell script. It's a scheduler daemon. Its execution model matters because cron jobs run in a minimal environment compared to your interactive terminal.

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

0 3 * * * /usr/bin/flock -n /tmp/backup.lock /opt/jobs/backup.sh >> /var/log/backup.log 2>&1
  • Use absolute paths for scripts and binaries.
  • Capture stdout/stderr so failures are visible in logs.
  • Prevent overlaps with locks when jobs can run longer than their interval.
  • Set environment explicitly instead of assuming profile files are loaded.
A cron line is more than timing. It defines operational behavior: runtime environment, concurrency assumptions, error visibility, and retry expectations.

Common Scheduling Mistakes

Most production cron bugs are not parser errors. They are time-model errors.

  1. DST surprises: in spring, some local times never occur; in fall, some happen twice.
  2. Timezone mismatch: server timezone differs from business timezone.
  3. Load spikes: too many jobs run at minute 0, creating avoidable bursts.
  4. Shell assumptions: command works manually but fails under cron due to PATH or missing env vars.
Practical rule: use UTC for infrastructure scheduling when possible. Convert to human-local display times in dashboards and notifications.

Using crontab -e in Real Workflows

The classic workflow is still relevant, especially for debugging incidents on Linux hosts:

  1. Open your user schedule with crontab -e.
  2. Add or update entries and save.
  3. Confirm with crontab -l.
  4. Observe first execution in logs before treating the job as reliable.
crontab -e   # edit current user's jobs
crontab -l   # list jobs
crontab -r   # remove all jobs (dangerous)

In modern teams, cron configs are often generated from infrastructure-as-code. But you still need cron literacy to interpret legacy jobs, audit schedules, and diagnose broken automation.

Why Cron Still Matters in 2026

Event systems and queue processors are great for reactive workloads. But recurring jobs are a different class of problem: compliance exports, nightly ETL, invoicing cycles, token rotation, and retention cleanup all need deterministic repetition. Cron remains the default language for that class of work.

Once you can read the five fields quickly and reason about timezone/DST behavior, cron stops feeling magical and starts feeling mechanical. That is exactly what you want from scheduling infrastructure.

Try it yourself

Put what you learned into practice with our Cron Expression Builder.