Automate recurring tasks with Linux's built-in scheduling tools. Master cron for reliable task automation.
Cron Basics
Cron runs scheduled tasks called "cron jobs" based on time expressions.
Crontab Syntax
* * * * * command
| | | | |
| | | | +-- Day of week (0-7, Sun=0 or 7)
| | | +---- Month (1-12)
| | +------ Day of month (1-31)
| +-------- Hour (0-23)
+---------- Minute (0-59)Examples
# Every minute
* * * * * /path/to/script.sh
# Every hour at minute 30
30 * * * * /path/to/script.sh
# Every day at 2:30 AM
30 2 * * * /path/to/script.sh
# Every Monday at 9 AM
0 9 * * 1 /path/to/script.sh
# First day of every month at midnight
0 0 1 * * /path/to/script.sh
# Every 15 minutes
*/15 * * * * /path/to/script.sh
# Every weekday at 6 PM
0 18 * * 1-5 /path/to/script.sh
# Twice daily (9 AM and 6 PM)
0 9,18 * * * /path/to/script.shSpecial Strings
@reboot # Run once at startup
@yearly # 0 0 1 1 *
@annually # Same as @yearly
@monthly # 0 0 1 * *
@weekly # 0 0 * * 0
@daily # 0 0 * * *
@midnight # Same as @daily
@hourly # 0 * * * *Managing Crontabs
# Edit your crontab
crontab -e
# View your crontab
crontab -l
# Remove your crontab
crontab -r
# Edit another user's crontab (root)
sudo crontab -u username -e
# View system-wide crontab
cat /etc/crontabSystem Cron Directories
# Drop scripts in these directories:
/etc/cron.d/ # Custom cron files
/etc/cron.hourly/ # Run every hour
/etc/cron.daily/ # Run daily
/etc/cron.weekly/ # Run weekly
/etc/cron.monthly/ # Run monthly
# Scripts must be executable and have no extension
sudo cp backup.sh /etc/cron.daily/backup
sudo chmod +x /etc/cron.daily/backupBest Practices
Use Absolute Paths
# BAD - might not find commands
0 2 * * * backup.sh
# GOOD - explicit paths
0 2 * * * /usr/local/bin/backup.shSet PATH and Environment
# At top of crontab
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
SHELL=/bin/bash
MAILTO=[email protected]
0 2 * * * /usr/local/bin/backup.shRedirect Output
# Silence output (no mail)
0 2 * * * /path/to/script.sh > /dev/null 2>&1
# Log output
0 2 * * * /path/to/script.sh >> /var/log/backup.log 2>&1
# Log with timestamp
0 2 * * * /path/to/script.sh >> /var/log/backup.log 2>&1 && echo "---\n$(date)" >> /var/log/backup.logPrevent Overlap
# Use flock to prevent concurrent runs
* * * * * /usr/bin/flock -n /tmp/myjob.lock /path/to/script.sh
# Or check in the script
#!/bin/bash
LOCKFILE=/tmp/myjob.lock
if [ -f "$LOCKFILE" ]; then
echo "Job already running"
exit 1
fi
trap "rm -f $LOCKFILE" EXIT
touch "$LOCKFILE"
# ... rest of scriptSystemd Timers (Modern Alternative)
Create Timer Unit
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup timer
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.targetCreate Service Unit
# /etc/systemd/system/backup.service
[Unit]
Description=Backup service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=backupEnable Timer
sudo systemctl daemon-reload
sudo systemctl enable backup.timer
sudo systemctl start backup.timer
# View timer status
systemctl list-timers
systemctl status backup.timerOnCalendar Examples
OnCalendar=hourly
OnCalendar=daily
OnCalendar=weekly
OnCalendar=*-*-* 02:00:00 # Daily at 2 AM
OnCalendar=Mon *-*-* 09:00:00 # Monday at 9 AM
OnCalendar=*-*-01 00:00:00 # First of month
OnCalendar=*:0/15 # Every 15 minutesOne-Time Tasks with at
# Run command at specific time
echo "/path/to/script.sh" | at 2:00 AM
# Run tomorrow
at tomorrow <<< "/path/to/script.sh"
# Run in 2 hours
at now + 2 hours <<< "/path/to/script.sh"
# Interactive mode
at 14:30
at> /path/to/script.sh
at> Ctrl+D
# List scheduled jobs
atq
# Remove job
atrm job_number
# View job details
at -c job_numberTroubleshooting
Check Cron is Running
systemctl status cron
# or
systemctl status crondView Cron Logs
# Debian/Ubuntu
grep CRON /var/log/syslog
# RHEL/CentOS
grep cron /var/log/cron
# Systemd journal
journalctl -u cronTest Cron Environment
# See what environment cron uses
* * * * * env > /tmp/cron-env.txt
# Then compare
diff /tmp/cron-env.txt <(env)Common Issues
Script works manually but not in cron
- Check PATH and use absolute paths
- Check file permissions
- Check environment variables
No output/mail
- Check MAILTO setting
- Check if mail is configured
- Redirect output to log file
Wrong timezone
- Check TZ in crontab
- System timezone: timedatectl
intermediate System Administration 20 min read
Related Tutorials
croncrontabschedulingsystemd timerautomationat