What Is a Cron Job in Linux? Complete Guide to Scheduled Tasks

2024/01/31 2026/05/16
What Is a Cron Job in Linux? Complete Guide to Scheduled Tasks

A cron job is a time-based task scheduler built into Linux and Unix systems. It automatically runs commands or scripts at specified intervals — every minute, hourly, daily, weekly, or on custom schedules. System administrators use cron jobs to automate backups, rotate logs, monitor services, and send scheduled reports without manual intervention.

In Linux, a cron job is the core tool for automating scheduled tasks. Once configured, the system automatically executes backups, log cleanup, service monitoring, and other repetitive tasks at specified times — greatly improving operational efficiency. This guide covers everything from cron fundamentals, time format syntax, and practical examples to debugging tips.

What Is a Cron Job?

Cron is a built-in scheduling utility in Unix-like systems (including Linux). Its name derives from the Greek word “chronos” (time). The cron daemon runs continuously in the background, checking the schedule configuration once every minute and automatically executing the corresponding commands or scripts when the time conditions are met.

Common use cases for cron jobs:

  • Automated backups: Back up databases or important files every night at 3 AM
  • Log cleanup: Periodically delete logs older than 30 days to prevent disk space exhaustion
  • System monitoring: Check whether services are running normally every few minutes
  • Report generation: Automatically generate analytics reports weekly and send them via email
  • Certificate renewal: Automatically renew SSL certificates (e.g., Let’s Encrypt’s certbot)

Cron Job vs systemd Timer

Modern Linux systems (especially Ubuntu 20.04+) also offer systemd timers as an alternative to cron. Each approach has its own strengths and weaknesses:

Comparison Cron Job systemd Timer
Configuration difficulty Simple, single-line setup More complex, requires two config files
Logging Must manually redirect to log files Automatically integrated with journald
Missed execution handling Missed runs are simply skipped Can be configured to run after boot (OnBootSec)
Dependency management Not supported Supports systemd service dependencies
Best suited for Quick, simple scheduled tasks Complex service management scheduling

For most everyday scheduling needs, cron job syntax is simple and effective, making it the most commonly used choice.


Crontab Time Format

The cron job time format consists of five fields followed by a command:

* * * * * command to execute
│ │ │ │ │
│ │ │ │ └── Day of Week (0-7, both 0 and 7 represent Sunday)
│ │ │ └──── Month (1-12)
│ │ └────── Day of Month (1-31)
│ └──────── Hour (0-23)
└────────── Minute (0-59)

Field Reference

Field Description Allowed Values
MIN Minute 0 to 59
HOUR Hour 0 to 23
DOM Day of Month 1 to 31
MON Month 1 to 12, or English abbreviations (Jan, Feb, Mar…)
DOW Day of Week 0 (Sunday) to 6 (Saturday), 7 also means Sunday, or English abbreviations (Sun, Mon…)
CMD Command to execute Any executable program or script (with arguments)

Special Characters

In addition to numeric values, cron supports the following special characters for more flexible scheduling:

Character Name Description Example
* Asterisk Every possible value * in the minute field = every minute
, Comma List multiple values 1,15,30 = at minute 1, 15, and 30
- Hyphen Specify a range 9-17 = from 9 AM to 5 PM
/ Slash Specify step intervals */5 = every 5 units

Crontab Cheat Sheet

Schedule Description Crontab Expression
Every minute * * * * *
Every 5 minutes */5 * * * *
Every 15 minutes */15 * * * *
Every hour on the hour 0 * * * *
Every day at 2:00 AM 0 2 * * *
Every day at 8:30 AM 30 8 * * *
Every Monday at 9:00 AM 0 9 * * 1
Every Monday, Wednesday, and Friday at 1:00 AM 0 1 * * 1,3,5
1st of every month at midnight 0 0 1 * *
Last day of month (approximate) at midnight 0 0 28-31 * *
January 1st at midnight (yearly) 0 0 1 1 *
Weekdays (Mon–Fri) at 8:00 AM 0 8 * * 1-5

Crontab Commands

Basic Commands

# Edit the current user's crontab (opens the default editor)
crontab -e

# List all scheduled jobs for the current user
crontab -l

# Remove all scheduled jobs for the current user (dangerous! back up first)
crontab -r

# Back up the current crontab to a file
crontab -l > ~/crontab_backup.txt

# Restore crontab from a backup file
crontab ~/crontab_backup.txt

Managing Other Users’ Crontabs

# Edit a specific user's crontab as root
sudo crontab -u username -e

# View a specific user's scheduled jobs
sudo crontab -u username -l

# Remove a specific user's scheduled jobs
sudo crontab -u username -r

Crontab Guru — Visual Cron Expression Editor

Crontab Guru
  • A handy tool that lets you quickly edit and preview the meaning of cron time expressions in real time — perfect for beginners unfamiliar with the syntax

Practical Scheduling Examples

Basic Examples

# Run a backup script every day at 3:00 AM
0 3 * * * /home/benz/scripts/backup.sh

# Delete logs older than 30 days every Monday at 2:00 AM
0 2 * * 1 find /var/log/app -name "*.log" -mtime +30 -delete

# Log disk usage every hour
0 * * * * df -h >> /var/log/disk_usage.log

# Check if nginx is running every 5 minutes; restart if it's not
*/5 * * * * systemctl is-active nginx || systemctl restart nginx

# Send a daily system status report email at 8:00 AM
0 8 * * * /home/benz/scripts/daily_report.sh | mail -s "Daily Report" admin@example.com

Advanced Examples (Logging and Error Handling)

By default, cron discards command output (or sends it via email through MAILTO). It is recommended to redirect both stdout and stderr to a log file for easier troubleshooting:

# Redirect both stdout and stderr to a log file
0 3 * * * /home/benz/scripts/backup.sh >> /var/log/cron_backup.log 2>&1

# 2>&1 means: redirect stderr (2) to wherever stdout (1) points
# >> appends to the file without overwriting existing content

# Log only errors
0 3 * * * /home/benz/scripts/backup.sh > /dev/null 2>> /var/log/cron_errors.log

# Add timestamps to log entries
0 * * * * echo "$(date '+%Y-%m-%d %H:%M:%S') - Execution completed" >> /var/log/hourly.log

Setting Environment Variables in Cron

# Set environment variables at the top of the crontab (applies to all jobs)
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=admin@example.com

# With MAILTO set, cron will automatically send an email whenever a job produces output
# Set it to an empty string to disable email notifications:
MAILTO=""

0 3 * * * /home/benz/scripts/backup.sh

Cron Job Environment Variables

This is the most common “gotcha” with cron jobs — a command that runs perfectly in your terminal fails when placed in cron. The cause is almost always different environment variables.

Why Are Cron’s Environment Variables Different from the Terminal?

When you log into a terminal, the system loads configuration files like .bashrc and .bash_profile, which set up environment variables such as PATH, JAVA_HOME, and others. However, cron runs in a non-interactive, minimal environment that does not load these configuration files, resulting in a very short PATH:

# PATH in your terminal (long, includes many custom paths)
echo $PATH
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/home/benz/.local/bin

# Default PATH in cron (very short)
# /usr/bin:/bin

Solutions

Method 1: Set PATH at the top of your crontab (Recommended)

# Add these lines at the top of crontab -e
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash

# All subsequent jobs will use this PATH
0 3 * * * backup.sh

Method 2: Use absolute paths in your commands

# Don't write
0 3 * * * node /home/benz/app/index.js

# Use the full path instead
0 3 * * * /usr/local/bin/node /home/benz/app/index.js

Method 3: Source environment configuration in your script

#!/bin/bash
# Load bash environment configuration at the start of the script
source /home/benz/.bashrc
# or
source /etc/profile

# Then run the actual logic
/usr/local/bin/node /home/benz/app/index.js

Cron Job Debugging Tips

When a scheduled job does not execute as expected, the following methods can help identify the problem:

1. Check Cron Logs in the System Journal

# View cron logs on Ubuntu/Debian systems
grep CRON /var/log/syslog | tail -50

# Or use journalctl (systemd-based systems)
journalctl -u cron --since "1 hour ago"

# Monitor cron logs in real time
tail -f /var/log/syslog | grep CRON

2. Verify the Cron Daemon Is Running

# Check the cron service status
systemctl status cron

# If it's not running, start it
sudo systemctl start cron
sudo systemctl enable cron  # Enable auto-start on boot

3. Test Commands in the Same Environment

# Simulate cron's execution environment for testing
env -i PATH=/usr/bin:/bin HOME=/home/benz SHELL=/bin/bash /home/benz/scripts/backup.sh

# Verify the script has execute permissions
ls -l /home/benz/scripts/backup.sh
chmod +x /home/benz/scripts/backup.sh

4. Common Issues Checklist

Problem Likely Cause Solution
Cron does not run at all cron service is not started systemctl start cron
Command not found PATH does not include the command’s directory Set PATH at the top of crontab or use absolute paths
Script has no execute permission File is missing the x permission chmod +x script.sh
File or directory not found Relative paths are used Use absolute paths (e.g., /home/benz/data/)
Runs but has no effect Missing environment variables Add source ~/.bashrc in the script

System-Level Cron Configuration

In addition to user-level crontab, Linux provides several system-level scheduling locations:

/etc/crontab — System-Wide Schedule

The /etc/crontab format includes an additional user field compared to user crontabs:

# /etc/crontab format (includes a username field)
# m h  dom mon dow   user    command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )

/etc/cron.d/ — Package-Specific Schedules

Packages often place their own schedule configurations in /etc/cron.d/, using the same format as /etc/crontab:

# List all system-level scheduled jobs
ls /etc/cron.d/

# Common entries include certbot (SSL certificate renewal)
cat /etc/cron.d/certbot

/etc/cron.daily/, cron.weekly/, cron.monthly/

These three directories contain scripts that the system automatically runs daily, weekly, or monthly:

ls /etc/cron.daily/
ls /etc/cron.weekly/
ls /etc/cron.monthly/

# Manually trigger a test run (simulate daily schedule execution)
run-parts /etc/cron.daily

anacron — For Computers That Are Not Always On

If a computer is not running 24/7 (such as a laptop), cron may miss scheduled jobs while the machine is off. anacron compensates by running missed jobs after the system boots:

# View anacron configuration
cat /etc/anacrontab

# Format explanation:
# 1      5   cron.daily   run-parts --report /etc/cron.daily
# period  delay  job-id     command

Cron Job Alternatives

While cron is the most widely-used scheduler, modern Linux offers alternatives for specific needs:

Tool Best For Key Advantage
cron Simple scheduled tasks One-line syntax, universally available
systemd timer Complex service scheduling Journald logging, dependency management
anacron Laptops/desktops (not always on) Runs missed jobs after boot
at One-time future execution Schedule a single run without recurring
systemd-run Quick one-off timers No config files needed

For most DevOps and sysadmin tasks, cron remains the standard choice due to its simplicity and universal support across all Linux distributions.


Frequently Asked Questions (FAQ)

Q1: Should I use cron job or systemd timer?

For most simple scheduling needs, cron job syntax is intuitive and quick to set up — making it the go-to choice. Consider systemd timers only if you need:

  • Precise logging (integrated with journald)
  • Task dependencies (a job must run only after a specific service starts)
  • Missed job recovery after boot (similar to anacron functionality)

Q2: Why does my cron job run fine in the terminal but fail when scheduled?

The three most common causes:

  1. PATH issue: Cron’s PATH is very short and cannot find your command. Solution: add PATH=... at the top of your crontab or use full paths in commands.
  2. Permission issue: The script does not have execute permission (chmod +x script.sh), or it accesses resources that require sudo.
  3. Relative path issue: The script uses relative paths, but cron’s working directory may not be what you expect. Use absolute paths instead.

Q3: Cron can only go down to one-minute intervals. Can I run something every second?

Cron’s minimum resolution is one minute — it cannot execute jobs every second. If you need per-second execution, consider these alternatives:

  • Loop within a script: Write while true; do command; sleep 1; done in a script, then use cron to launch it
  • systemd timer: Use OnCalendar=*:*:0/5 to achieve execution every 5 seconds
  • Background daemon service: For long-term needs, consider writing a systemd service that runs continuously

Further reading:

BenZ Software Developer

Software developer passionate about technology. Sharing programming experiences and learning notes.