How to Set Up a Cron Job in Linux (with Examples)

6 min read
Beginner Linux Cron Automation Scheduling How To

Quick Answer: Edit crontab: crontab -e. Add a job: 0 2 * /opt/backup.sh (runs at 2:00 AM daily). View jobs: crontab -l. Format: minute hour day month weekday command.


Cron Syntax

┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * * command
Field Values Special
Minute 0-59 * = every minute
Hour 0-23 * = every hour
Day of month 1-31 * = every day
Month 1-12 * = every month
Day of week 0-7 0 and 7 = Sunday

Special Characters

Character Meaning Example
* Every value * = every minute
, List 1,15 = minute 1 and 15
- Range 1-5 = minutes 1 through 5
/ Step /10 * = every 10 minutes

Common Schedules

Expression When It Runs
* Every minute
/5 * Every 5 minutes
/15 * Every 15 minutes
0 Every hour (at :00)
0 /2 Every 2 hours
0 0 * Every day at midnight
0 2 * Every day at 2:00 AM
0 9 1-5 Weekdays at 9:00 AM
0 0 0 Every Sunday at midnight
0 0 1 First of every month at midnight
0 0 1 1 * January 1st at midnight (yearly)
30 4 1 Every Monday at 4:30 AM
0 9,17 * 9:00 AM and 5:00 PM daily

Shortcut Strings

Shortcut Equivalent When
@reboot Once at startup
@yearly 0 0 1 1 * Once a year
@monthly 0 0 1 Once a month
@weekly 0 0 0 Once a week
@daily 0 0 * Once a day
@hourly 0 Once an hour

Managing Crontab

# Edit your crontab
crontab -e

# View your crontab
crontab -l

# Remove your crontab (deletes ALL jobs)
crontab -r

# Edit another user's crontab
sudo crontab -u sam -e

# View another user's crontab
sudo crontab -u sam -l

First time? crontab -e will ask which editor to use. Pick nano for simplicity.


Practical Examples

Backups

# Daily database backup at 2 AM
0 2 * * * docker exec postgres pg_dumpall -U postgres | gzip > /backups/db-$(date +\%Y\%m\%d).sql.gz

# Weekly full backup on Sunday at 3 AM
0 3 * * 0 tar czf /backups/weekly-$(date +\%Y\%m\%d).tar.gz /var/www/

# Delete backups older than 30 days (runs daily at 4 AM)
0 4 * * * find /backups -name "*.gz" -mtime +30 -delete

Monitoring

# Check if website is up every 5 minutes
*/5 * * * * curl -sf https://samnet.dev > /dev/null || echo "Site down!" | mail -s "Alert" [email protected]

# Log disk usage hourly
0 * * * * df -h >> /var/log/disk-usage.log

# Restart service if it crashes (check every minute)
* * * * * systemctl is-active --quiet nginx || systemctl restart nginx

Maintenance

# Update system packages weekly (Sunday 4 AM)
0 4 * * 0 apt update && apt upgrade -y >> /var/log/apt-update.log 2>&1

# Clear temp files daily at midnight
0 0 * * * find /tmp -type f -mtime +7 -delete

# Renew SSL certificates (twice daily, certbot handles timing)
0 0,12 * * * certbot renew --quiet

# Rotate logs weekly
0 0 * * 0 logrotate /etc/logrotate.conf

Scripts

# Run a Python script every hour
0 * * * * /usr/bin/python3 /opt/scripts/report.py >> /var/log/report.log 2>&1

# Run a Bash script at startup
@reboot /opt/scripts/startup.sh

# Run Node.js script every 30 minutes
*/30 * * * * cd /opt/myapp && /usr/bin/node index.js >> /var/log/myapp.log 2>&1

Important Tips

Use Full Paths

Cron runs with a minimal environment. Always use full paths:

# Wrong (may not find the command)
0 * * * * python3 script.py

# Correct (full paths)
0 * * * * /usr/bin/python3 /opt/scripts/script.py

Find the full path: which python3

Escape Percent Signs

In crontab, % has special meaning (newline). Escape it with \:

# Wrong
0 2 * * * echo $(date +%Y%m%d)

# Correct
0 2 * * * echo $(date +\%Y\%m\%d)

Redirect Output

By default, cron emails output. Redirect to a file or discard:

# Log output to file
0 2 * * * /opt/backup.sh >> /var/log/backup.log 2>&1

# Discard all output
0 2 * * * /opt/backup.sh > /dev/null 2>&1

# Log errors only
0 2 * * * /opt/backup.sh > /dev/null

Set Environment Variables

# Add at the top of crontab
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
[email protected]

# Then your jobs
0 2 * * * /opt/backup.sh

System Cron Files

Besides per-user crontabs, there are system-wide cron directories:

# System crontab (has an extra "user" field)
/etc/crontab

# Drop-in directories (just place a script here)
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/

# Example: daily cleanup script
sudo nano /etc/cron.daily/cleanup
# Add script content, then:
sudo chmod +x /etc/cron.daily/cleanup

Troubleshooting

# Check if cron is running
systemctl status cron
# or
systemctl status crond    # CentOS/RHEL

# View cron logs
grep CRON /var/log/syslog
# or
journalctl -u cron

# Test your command manually first
/opt/scripts/backup.sh
# If it works manually but not in cron, it's usually a PATH or permissions issue
Problem Fix
Job doesn't run Check systemctl status cron. Check syntax with crontab validator
Command not found Use full paths (/usr/bin/python3 not python3)
Permission denied Make script executable: chmod +x script.sh
% in command breaks Escape as \%
No output/logging Add >> /var/log/job.log 2>&1
Wrong timezone Check timedatectl. Cron uses system timezone
Runs but does nothing Environment differs from shell. Set PATH in crontab
Email flooding Add > /dev/null 2>&1 or set MAILTO=""

Related Guides

Related Tools