October 4, 2026 · Yunus Emre Vurgun

How Do Cron Jobs Work?

devops · cli · tutorial · reference

Cron is the time-based job scheduler built into Unix-like systems: you describe when a command should run with five time fields, and the cron daemon runs it for you, every minute, hour, day, or month. A single line like 0 6 * * * /opt/backup.sh means run the backup script at 6 AM daily. This guide explains the syntax, common schedules, and the mistakes that trip up nearly everyone.

How the five time fields work

Every cron entry has five time fields followed by the command. Each field is a filter: the job runs when the current time matches all five at once.

FieldAllowed valuesMeaning
minute0-59Minute within the hour
hour0-23Hour of the day, 24-hour clock
day of month1-31Calendar day
month1-12 or JAN-DECMonth of the year
day of week0-7 or SUN-SATWeekday, where 0 and 7 both mean Sunday

A star means every possible value, so * * * * * runs every minute. Commas list specific values (0 9,17 * * * runs at 9 AM and 5 PM), dashes express ranges (0 9-17 * * 1-5 runs hourly on weekdays), and slashes add steps (*/15 * * * * runs every fifteen minutes). Combine them freely: 30 2 1 * * runs at 2:30 AM on the first of each month.

Schedule examples you can copy

These cover the schedules people actually need. Adjust the command path and redirect output to a log so silent failures leave a trace.

ScheduleCron line
Every 5 minutes*/5 * * * * /opt/healthcheck.sh >> /var/log/health.log 2>&1
Hourly at minute 00 * * * * /opt/aggregate-stats.sh
Daily at 3:15 AM15 3 * * * /opt/backup.sh
Weekdays at 8 AM0 8 * * 1-5 /opt/send-report.sh
Sunday at midnight0 0 * * 0 /opt/weekly-cleanup.sh
First of month, 1 AM0 1 1 * * /opt/monthly-invoice.sh
On every reboot@reboot /opt/start-worker.sh
Daily shorthand@daily /opt/rotate-logs.sh

Cron also accepts the shorthands @reboot, @yearly, @monthly, @weekly, @daily, and @hourly. They read better than the equivalent field patterns and mean exactly the same thing. Note that @reboot runs once when the cron daemon starts, which is normally at boot — handy for services that must survive restarts.

Managing the crontab

Each user has their own crontab, edited with crontab -e and listed with crontab -l. Always keep a backup copy of your crontab in version control, because crontab -r removes it with no confirmation and no undo.

crontab -l              # list your cron jobs
crontab -e              # edit your cron jobs
crontab -l > cron-backup.txt   # back up before changes
sudo crontab -u www-data -e  # edit another user's crontab

System-wide schedules live in /etc/crontab and /etc/cron.d/, which add a username field between the time and the command. The /etc/cron.hourly, daily, weekly, and monthly directories offer an even simpler option: drop an executable script in and the system runs it on that cadence. For the scripting side, the shell scripting guide covers the constructs cron jobs are usually written in.

Mistakes almost everyone makes with cron

Cron jobs fail in predictable ways, and nearly all of them trace back to the minimal environment cron provides. A script that works in your terminal can fail under cron because the PATH is tiny, the working directory is your home folder, and there is no interactive shell profile loaded.

  1. Relative paths. Cron runs with a minimal PATH and your home directory as cwd. Use absolute paths for every binary and file, or set PATH and cd explicitly at the top of the script.
  2. Missing environment. Variables from .bashrc, virtualenvs, and secret managers are not loaded. Source what you need inside the script or define variables at the top of the crontab.
  3. Silent failures. Cron emails output to the job owner, which on most servers goes nowhere. Redirect stdout and stderr to a log file on every line so failures are visible.
  4. Overlapping runs. If a job takes longer than its interval, two copies run at once and can corrupt shared state. Use a lock file with flock to serialize runs.
  5. Day-of-month versus day-of-week. When both fields are restricted, cron runs when either matches, not both. 0 0 1 * 0 runs on the first of the month AND every Sunday, which surprises people yearly.

A robust daily job therefore looks like this: absolute paths, explicit shell, a lock, and logged output. Long-running work started by cron is also worth watching with the tools in the process management commands entry, and the monitoring and logging tools catalog page lists options for alerting when a scheduled job stops succeeding.

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
15 3 * * * /usr/bin/flock -n /tmp/backup.lock /opt/backup.sh >> /var/log/backup.log 2>&1

How do I test a cron job without waiting for the schedule?

Run the exact command line yourself in a clean environment first: env -i SHELL=/bin/bash PATH=/usr/bin:/bin /opt/backup.sh approximates what cron sees and exposes missing variables immediately. Then, to verify the schedule itself, set the entry to run two minutes in the future, watch the log, and restore the real schedule once output appears. Many teams also keep a staging host where new entries run on short intervals for a day before promotion. If a job works by hand but not from cron, the cause is the environment in roughly nine cases out of ten — diff the two with env output captured from both contexts.

When cron is not enough

Cron is perfect for simple recurring commands on one machine, but it has no retries, no alerting, no coordination across hosts, and no visibility into run history. When you need dependencies between jobs, exactly-once execution, or schedules that skip holidays, reach for a real scheduler: systemd timers for single-host jobs with logging and failure handling, or a distributed scheduler like Airflow or Temporal for pipelines. A good rule of thumb is that cron owns commands a human could retype, while anything with ordering, retries, or cross-machine state deserves a scheduler with a proper run history. For the surrounding automation, the Unix file commands cheat sheet covers the file operations cron scripts perform most.