The Complete Guide to Cron Job Scheduling

February 9, 2026

Cron is one of the most useful utilities in Linux and Unix-like systems. It lets you schedule tasks to run automatically at specific times or intervals, whether that means running a backup every night, clearing temp files every hour, or sending a report every Monday morning. If you have ever needed something to happen on a schedule without you being there to press the button, cron is the answer.

This guide will walk you through everything you need to know about cron job scheduling: the syntax, the commands, practical examples, and the mistakes that trip up nearly everyone at some point. You can test any cron expression from this guide using our Cron Expression Parser.

⚙ Try it: Build your cron schedule: Use our Cron Expression Parser to build and verify cron schedules interactively.

What Is Cron?

Cron is a time-based job scheduler built into virtually every Linux and Unix system. It runs as a background daemon (crond) that wakes up every minute, checks a list of scheduled tasks, and executes any that are due. Each scheduled task is called a cron job, and the file that holds a user's list of jobs is called a crontab (short for "cron table").

Cron has been around since the 1970s, and for good reason: it is simple, reliable, and does exactly one thing well. You describe when something should run using a compact expression, and cron handles the rest. There is no GUI, no cloud dependency, and no subscription. It just works.

Understanding Cron Expression Syntax

A cron expression is a string of five fields separated by spaces. Each field represents a unit of time, and together they define the schedule. The format is:

* * * * * command_to_run
| | | | |
| | | | +---- Day of week (0-7, where 0 and 7 are Sunday)
| | | +------ Month (1-12)
| | +-------- Day of month (1-31)
| +---------- Hour (0-23)
+------------ Minute (0-59)

The Five Fields Explained

Field Allowed Values Description
Minute 0–59 The exact minute the job should run
Hour 0–23 The hour in 24-hour format (0 = midnight, 23 = 11 PM)
Day of Month 1–31 The calendar day (note: not all months have 31 days)
Month 1–12 The month of the year (1 = January, 12 = December)
Day of Week 0–7 The weekday (0 and 7 both represent Sunday, 1 = Monday)

Each field can contain a single value, a range, a list, or a step value. An asterisk (*) means "every possible value" for that field.

Special Characters in Cron Expressions

Cron supports several special characters that give you flexibility beyond simple fixed values:

Character Meaning Example
* Any value (wildcard) * * * * * — every minute
, List of values 0,15,30,45 * * * * — minutes 0, 15, 30, 45
- Range of values 0 9-17 * * * — every hour from 9 AM to 5 PM
/ Step values */10 * * * * — every 10 minutes

You can also combine these. For instance, 1-30/5 in the minute field means "every 5 minutes during the first half of each hour" (minutes 1, 6, 11, 16, 21, 26).

Practical Cron Expression Examples

Here are the most common schedules you will actually use in practice. Try pasting any of these into our Cron Expression Parser to see the next run times.

Every Minute

* * * * * /path/to/script.sh

Runs once per minute. Useful for monitoring checks or queue processing, but be careful with resource-heavy tasks.

Every 5 Minutes

*/5 * * * * /path/to/script.sh

A common choice for health checks, cache warming, or polling an API.

Every Hour (on the Hour)

0 * * * * /path/to/script.sh

Runs at minute 0 of every hour. Good for hourly log rotation or report generation.

Every Day at Midnight

0 0 * * * /path/to/backup.sh

The classic daily job. Runs at 00:00 every day. Commonly used for database backups, log cleanup, and daily digest emails.

Every Day at 6:30 AM

30 6 * * * /path/to/morning-report.sh

Useful for triggering reports or notifications before the workday starts.

Every Monday at 9 AM

0 9 * * 1 /path/to/weekly-task.sh

Weekly tasks like sending summary reports, weekly backups, or database maintenance.

Weekdays Only at 8 AM

0 8 * * 1-5 /path/to/workday-task.sh

Runs Monday through Friday. Perfect for business-hours tasks that should not run on weekends.

First Day of Every Month at 2 AM

0 2 1 * * /path/to/monthly-report.sh

Monthly tasks like generating invoices, billing reports, or archiving old data.

Every 15 Minutes During Business Hours

*/15 9-17 * * 1-5 /path/to/check.sh

Runs every 15 minutes, but only between 9 AM and 5 PM on weekdays. A practical pattern for monitoring systems that only matter during working hours.

Twice a Day (8 AM and 8 PM)

0 8,20 * * * /path/to/sync.sh

Uses a comma-separated list in the hour field to run at two specific times each day.

Every Sunday at 3 AM (Weekly Maintenance)

0 3 * * 0 /path/to/maintenance.sh

A typical slot for weekly maintenance: off-hours on a weekend to minimize disruption.

January 1st at Midnight (Yearly)

0 0 1 1 * /path/to/yearly-archive.sh

Runs once a year. Useful for annual log rotation or yearly summary generation.

Predefined Schedule Shortcuts

Most cron implementations support shorthand strings that replace the five-field expression:

Shorthand Equivalent Description
@reboot N/A Run once at system startup
@yearly 0 0 1 1 * Once a year (midnight, January 1)
@monthly 0 0 1 * * Once a month (midnight, first day)
@weekly 0 0 * * 0 Once a week (midnight on Sunday)
@daily 0 0 * * * Once a day (midnight)
@hourly 0 * * * * Once an hour (at minute 0)

These shortcuts are convenient and self-documenting. Using @daily immediately communicates intent better than 0 0 * * * does.

Essential Crontab Commands

You interact with cron through the crontab command. Here are the commands every developer needs to know:

View Your Crontab

crontab -l

Lists all cron jobs for the current user. If you have never created one, it will say "no crontab for [username]".

Edit Your Crontab

crontab -e

Opens your crontab in the system's default text editor (usually vi or nano). When you save and exit, cron automatically picks up the changes. There is no need to restart the daemon.

Remove Your Crontab

crontab -r

Deletes your entire crontab. Be careful with this one — it removes all jobs, not just one. There is no confirmation prompt.

Edit Another User's Crontab (as Root)

sudo crontab -u username -e

As root, you can view or edit another user's crontab. This is useful for managing service accounts that do not have interactive logins.

System-Wide Cron Jobs

Besides per-user crontabs, Linux has system-wide cron directories:

To use the .hourly, .daily, .weekly, or .monthly directories, simply drop an executable script into the appropriate folder. No cron expression needed — the system handles the scheduling.

Environment and Path Issues

This is where most cron beginners hit their first wall. Cron jobs do not run with the same environment as your interactive shell. Specifically:

The safest approach is to use absolute paths for everything:

# Bad: relies on PATH
0 2 * * * python3 /home/user/backup.py

# Good: uses absolute path to the interpreter
0 2 * * * /usr/bin/python3 /home/user/backup.py

You can find the full path to any command with which:

which python3
# /usr/bin/python3

Alternatively, you can set the PATH at the top of your crontab:

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

0 2 * * * python3 /home/user/backup.py

Handling Output and Logging

By default, cron captures the standard output and standard error from every job and tries to email it to the user who owns the crontab. On many modern systems, local mail is not configured, so this output silently vanishes.

You should always redirect output explicitly:

Log to a File

# Redirect stdout and stderr to a log file
0 2 * * * /usr/bin/python3 /home/user/backup.py >> /var/log/backup.log 2>&1

Discard Output Completely

# Send everything to /dev/null (silent mode)
0 2 * * * /usr/bin/python3 /home/user/backup.py > /dev/null 2>&1

Log stdout and stderr Separately

0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>> /var/log/backup-errors.log

Always log output during development and testing. You can switch to silent mode once you are confident the job works correctly.

Troubleshooting Cron Jobs

When a cron job does not run or produces unexpected results, work through this checklist:

1. Check That Cron Is Running

systemctl status cron
# or on some systems:
systemctl status crond

If the service is not active, start it with sudo systemctl start cron.

2. Check the System Log

# Debian/Ubuntu
grep CRON /var/log/syslog

# CentOS/RHEL
grep CRON /var/log/cron

The system log will show you when cron attempted to run your job. If your job does not appear at all, the cron expression is wrong or the crontab was not saved correctly.

3. Verify the Crontab Was Saved

crontab -l

Make sure your job actually appears. A common mistake is editing the crontab in vi and exiting without saving (:q! instead of :wq).

4. Test the Command Manually

Copy the exact command from your crontab and run it in a minimal shell environment:

env -i /bin/sh -c '/usr/bin/python3 /home/user/backup.py'

This simulates the stripped-down environment that cron provides. If it fails here, it will fail in cron too.

5. Check File Permissions

The script must be executable and readable by the user whose crontab it is in:

chmod +x /home/user/backup.sh
ls -la /home/user/backup.sh

6. Check for Newline at End of File

This is a classic gotcha. The crontab must end with a newline character. If the last line of your crontab does not have a trailing newline, cron may silently ignore it. Most text editors add one automatically, but it is worth verifying if a job mysteriously refuses to run.

Best Practices for Cron Jobs

Cron vs. Systemd Timers

Modern Linux systems running systemd offer an alternative to cron called systemd timers. Timers are more verbose to configure but offer advantages like built-in logging (via journald), dependency management, and better resource controls. However, cron remains the standard for most use cases because of its simplicity and universal availability.

Use cron when you need a quick, portable, and straightforward scheduled task. Consider systemd timers when you need advanced features like randomized delays, calendar-based scheduling with second precision, or tight integration with other systemd services.

Quick Reference Cheat Sheet

# Every minute
* * * * *

# Every 5 minutes
*/5 * * * *

# Every hour
0 * * * *

# Every day at midnight
0 0 * * *

# Every Monday at 9 AM
0 9 * * 1

# Weekdays at 8 AM
0 8 * * 1-5

# First of month at 2 AM
0 2 1 * *

# Every 15 min, business hours, weekdays
*/15 9-17 * * 1-5

# Twice a day (8 AM and 8 PM)
0 8,20 * * *

# On system reboot
@reboot

Next Steps

The best way to get comfortable with cron expressions is to practice reading and writing them. Head over to our Cron Expression Parser to test expressions and see exactly when they will run next. You can also explore our cheat sheets for more quick-reference developer resources.

Cron has been quietly running scheduled tasks on servers for over 50 years, and there is good reason it is still the default choice for most developers. Learn the five-field syntax, remember to use absolute paths, redirect your output, and you will have reliable task automation with almost zero overhead.

Related Resources

Cron Expression Parser
Parse and verify cron expressions
Bash Shortcuts Cheat Sheet
Essential terminal shortcuts
Linux Permissions Cheat Sheet
File permissions reference