Back to Blog
CronLinuxAutomation

Cron Job Syntax: Schedule Tasks Like a Pro

March 30, 2026 · 6 min read

Cron is the time-based job scheduler built into Unix-like systems. It runs commands or scripts at fixed times or intervals — backups at midnight, report generation every Monday, cache invalidation every 15 minutes. The syntax is compact but unintuitive at first glance. This guide makes it readable.

The Five-Field Format

┌───────────── minute        (0–59)
│ ┌─────────── hour          (0–23)
│ │ ┌───────── day of month  (1–31)
│ │ │ ┌─────── month         (1–12 or JAN–DEC)
│ │ │ │ ┌───── day of week   (0–7 or SUN–SAT, 0 and 7 are both Sunday)
│ │ │ │ │
* * * * * command to execute

Field Values

*        any value (every minute, every hour, etc.)
5        specific value (exactly 5)
5,10,15  list of values (at 5, 10, and 15)
1-5      range (every value from 1 to 5, inclusive)
*/5      step (every 5th: 0, 5, 10, 15, ...)
1-10/2   range with step (1, 3, 5, 7, 9)

Common Schedules

# Every minute
* * * * *

# Every 5 minutes
*/5 * * * *

# Every hour, on the hour
0 * * * *

# Every day at midnight
0 0 * * *

# Every day at 2:30 AM
30 2 * * *

# Every Monday at 9:00 AM
0 9 * * 1

# Every weekday (Mon–Fri) at 8:00 AM
0 8 * * 1-5

# Every weekend at noon
0 12 * * 6,0

# First day of every month at midnight
0 0 1 * *

# Every 6 hours
0 */6 * * *

# Twice a day (noon and midnight)
0 0,12 * * *

# Every 15 minutes between 9 AM and 5 PM on weekdays
*/15 9-17 * * 1-5

Special Strings

Most cron implementations support predefined shorthand strings:

StringMeaningEquivalent
@yearly / @annuallyOnce a year, Jan 1 midnight0 0 1 1 *
@monthlyFirst day of each month at midnight0 0 1 * *
@weeklyEvery Sunday at midnight0 0 * * 0
@daily / @midnightEvery day at midnight0 0 * * *
@hourlyEvery hour, on the hour0 * * * *
@rebootOnce at startup

Editing the Crontab

crontab -e          # edit your crontab (opens in $EDITOR)
crontab -l          # list current crontab
crontab -r          # delete your crontab (be careful!)
crontab -u alice -e # edit another user's crontab (root only)

# System-wide crontabs (different format — includes user field)
/etc/cron.d/my-job
/etc/crontab

The format in /etc/crontab and /etc/cron.d/ adds a username field after the five time fields:

# /etc/cron.d/backup
0 3 * * * root /usr/local/bin/backup.sh

Output and Logging

By default, cron emails output to the local user. On most production servers there is no mail server, so jobs silently fail. Always redirect output explicitly:

# Discard all output
0 * * * * /path/to/script.sh > /dev/null 2>&1

# Log stdout and stderr to a file
0 * * * * /path/to/script.sh >> /var/log/myjob.log 2>&1

# Log with timestamp
0 * * * * date >> /var/log/myjob.log && /path/to/script.sh >> /var/log/myjob.log 2>&1

Environment Variables in Cron

Cron runs with a minimal environment — no PATH, no shell aliases, no .bashrc. Scripts that work in your terminal often fail in cron because commands are not found. Fix this by using absolute paths or setting PATH at the top of the crontab:

# At the top of crontab -e
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
MAILTO=""          # disable email output

0 * * * * python3 /home/alice/scripts/report.py

Testing Cron Jobs

The hardest part of cron is that you cannot easily test a schedule without waiting. A few strategies: set the schedule to * * * * * (every minute) during development, then fix it once it works. Run the command manually as the cron user (sudo -u www-data bash -c "/path/to/script.sh") to catch environment issues. Check /var/log/syslog or journalctl -u cron for execution logs.

Use the DateTime Tools on io9.me to verify your cron schedule lines up with the correct UTC times.