Cron Jobs and Task Scheduling
Complete guide to cron jobs and task scheduling for automated system maintenance. Learn cron syntax, scheduling patterns, and modern alternatives for reliable task automation.
Cron Jobs and Task Scheduling
Cron jobs are essential for automating repetitive tasks on Unix-like systems. They allow you to schedule scripts and commands to run at specific times, making them perfect for system maintenance, backups, monitoring, and other routine operations.
What are Cron Jobs?
Definition and Purpose
Cron jobs are scheduled tasks that run automatically at specified times. They are managed by the cron daemon, which checks for scheduled tasks every minute and executes them when their time conditions are met.
Key Benefits
- Automation: Run tasks without manual intervention
- Reliability: Consistent execution of routine tasks
- Efficiency: Optimize system resources and workflows
- Monitoring: Automated system health checks
- Maintenance: Regular cleanup and optimization tasks
Common Use Cases
- System Backups: Automated database and file backups
- Log Rotation: Clean up old log files
- System Monitoring: Health checks and alerts
- Data Processing: Batch processing of files
- Security Updates: Automated system updates
- Report Generation: Scheduled report creation
Cron Syntax and Format
Basic Cron Format
* * * * * command
ā ā ā ā ā
ā ā ā ā āāāā Day of week (0-7, Sunday = 0 or 7)
ā ā ā āāāāāā Month (1-12)
ā ā āāāāāāāā Day of month (1-31)
ā āāāāāāāāāā Hour (0-23)
āāāāāāāāāāāā Minute (0-59)
Special Characters
Asterisk (*)
- Meaning: Any value
- Example:
* * * * *(every minute) - Usage: Run task at all possible times
Comma (,)
- Meaning: List of values
- Example:
0 9,17 * * *(9 AM and 5 PM daily) - Usage: Run task at specific times
Hyphen (-)
- Meaning: Range of values
- Example:
0 9-17 * * *(every hour from 9 AM to 5 PM) - Usage: Run task during a time range
Slash (/)
- Meaning: Step values
- Example:
*/15 * * * *(every 15 minutes) - Usage: Run task at regular intervals
Question Mark (?)
- Meaning: No specific value
- Example:
0 0 ? * *(daily at midnight) - Usage: Used in day fields when not specifying
Common Cron Patterns
Daily Tasks
# Every day at midnight
0 0 * * * /path/to/script.sh
# Every day at 2 AM
0 2 * * * /path/to/backup.sh
# Every day at 6 PM
0 18 * * * /path/to/cleanup.sh
Weekly Tasks
# Every Sunday at midnight
0 0 * * 0 /path/to/weekly-backup.sh
# Every Monday at 9 AM
0 9 * * 1 /path/to/weekly-report.sh
# Every Friday at 5 PM
0 17 * * 5 /path/to/weekly-cleanup.sh
Monthly Tasks
# First day of every month at midnight
0 0 1 * * /path/to/monthly-backup.sh
# Last day of every month at 11 PM
0 23 28-31 * * /path/to/monthly-cleanup.sh
Frequent Tasks
# Every 5 minutes
*/5 * * * * /path/to/monitor.sh
# Every hour
0 * * * * /path/to/hourly-task.sh
# Every 2 hours
0 */2 * * * /path/to/bihourly-task.sh
Managing Cron Jobs
Viewing Cron Jobs
List User's Cron Jobs
# View current user's cron jobs
crontab -l
# View specific user's cron jobs (requires sudo)
sudo crontab -l -u username
System-wide Cron Jobs
# View system cron jobs
sudo cat /etc/crontab
# View cron jobs in /etc/cron.d/
ls -la /etc/cron.d/
# View daily, weekly, monthly cron jobs
ls -la /etc/cron.daily/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/
Editing Cron Jobs
Using crontab Command
# Edit current user's cron jobs
crontab -e
# Edit specific user's cron jobs
sudo crontab -e -u username
# Edit system crontab
sudo nano /etc/crontab
Direct File Editing
# Edit user's cron file directly
nano ~/.crontab
# Install from file
crontab ~/.crontab
Installing and Removing Cron Jobs
Installing Cron Jobs
# Install from file
crontab /path/to/cronfile
# Add single job
echo "0 2 * * * /path/to/script.sh" | crontab -
# Add multiple jobs
cat << EOF | crontab -
0 2 * * * /path/to/backup.sh
0 3 * * * /path/to/cleanup.sh
EOF
Removing Cron Jobs
# Remove all cron jobs for current user
crontab -r
# Remove specific user's cron jobs
sudo crontab -r -u username
# Remove specific job (edit and remove line)
crontab -e
Practical Cron Job Examples
System Maintenance
Daily Backup Script
#!/bin/bash
# daily_backup.sh
# Configuration
BACKUP_DIR="/backups/daily"
SOURCE_DIR="/var/www/html"
DATE=$(date +%Y%m%d)
LOG_FILE="/var/log/backup.log"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Create backup
tar -czf "$BACKUP_DIR/backup_$DATE.tar.gz" "$SOURCE_DIR"
# Log the backup
echo "$(date): Backup completed - backup_$DATE.tar.gz" >> "$LOG_FILE"
# Remove backups older than 7 days
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete
# Log cleanup
echo "$(date): Old backups cleaned up" >> "$LOG_FILE"
Log Rotation Script
#!/bin/bash
# log_rotation.sh
LOG_DIR="/var/log"
MAX_SIZE="100M"
MAX_FILES=5
# Rotate logs larger than MAX_SIZE
find "$LOG_DIR" -name "*.log" -size +$MAX_SIZE -exec logrotate -f /etc/logrotate.conf {} \;
# Compress old logs
find "$LOG_DIR" -name "*.log.*" -mtime +1 -exec gzip {} \;
# Remove old compressed logs
find "$LOG_DIR" -name "*.log.*.gz" -mtime +30 -delete
echo "$(date): Log rotation completed" >> /var/log/log_rotation.log
System Monitoring Script
#!/bin/bash
# system_monitor.sh
# Check disk usage
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
echo "WARNING: Disk usage is ${DISK_USAGE}%" | mail -s "Disk Usage Alert" admin@example.com
fi
# Check memory usage
MEM_USAGE=$(free | awk 'NR==2{printf "%.2f", $3*100/$2}')
if (( $(echo "$MEM_USAGE > 90" | bc -l) )); then
echo "WARNING: Memory usage is ${MEM_USAGE}%" | mail -s "Memory Usage Alert" admin@example.com
fi
# Check running processes
if ! pgrep -x "nginx" > /dev/null; then
echo "WARNING: Nginx is not running" | mail -s "Service Alert" admin@example.com
fi
Database Maintenance
Database Backup Script
#!/bin/bash
# db_backup.sh
# Configuration
DB_NAME="myapp"
DB_USER="backup_user"
DB_PASS="backup_password"
BACKUP_DIR="/backups/database"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Create database backup
mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$BACKUP_DIR/db_backup_$DATE.sql"
# Compress backup
gzip "$BACKUP_DIR/db_backup_$DATE.sql"
# Remove backups older than 30 days
find "$BACKUP_DIR" -name "db_backup_*.sql.gz" -mtime +30 -delete
echo "$(date): Database backup completed" >> /var/log/db_backup.log
Database Optimization Script
#!/bin/bash
# db_optimize.sh
DB_NAME="myapp"
DB_USER="admin"
DB_PASS="admin_password"
# Optimize database tables
mysql -u "$DB_USER" -p"$DB_PASS" -e "OPTIMIZE TABLE $DB_NAME.*;"
# Analyze tables
mysql -u "$DB_USER" -p"$DB_PASS" -e "ANALYZE TABLE $DB_NAME.*;"
echo "$(date): Database optimization completed" >> /var/log/db_optimize.log
Web Application Tasks
Cache Cleanup Script
#!/bin/bash
# cache_cleanup.sh
CACHE_DIR="/var/www/html/cache"
TEMP_DIR="/tmp"
# Clear application cache
find "$CACHE_DIR" -type f -name "*.cache" -mtime +1 -delete
# Clear temporary files
find "$TEMP_DIR" -name "tmp_*" -mtime +1 -delete
# Clear old session files
find /var/lib/php/sessions -name "sess_*" -mtime +7 -delete
echo "$(date): Cache cleanup completed" >> /var/log/cache_cleanup.log
SSL Certificate Renewal Check
#!/bin/bash
# ssl_check.sh
DOMAIN="example.com"
CERT_PATH="/etc/ssl/certs/$DOMAIN.crt"
DAYS_THRESHOLD=30
# Check certificate expiration
if [ -f "$CERT_PATH" ]; then
EXPIRY_DATE=$(openssl x509 -in "$CERT_PATH" -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_UNTIL_EXPIRY=$(( (EXPIRY_EPOCH - CURRENT_EPOCH) / 86400 ))
if [ $DAYS_UNTIL_EXPIRY -lt $DAYS_THRESHOLD ]; then
echo "WARNING: SSL certificate expires in $DAYS_UNTIL_EXPIRY days" | mail -s "SSL Certificate Alert" admin@example.com
fi
fi
Modern Alternatives to Cron
Systemd Timers
Creating a Systemd Timer
# Create service file
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Daily Backup Service
[Service]
Type=oneshot
ExecStart=/path/to/backup.sh
User=backup
Group=backup
# Create timer file
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
# Enable and start timer
sudo systemctl enable backup.timer
sudo systemctl start backup.timer
# Check timer status
systemctl list-timers
Anacron
Anacron Configuration
# Edit anacrontab
sudo nano /etc/anacrontab
# Format: period delay job-identifier command
1 5 backup.daily /path/to/backup.sh
7 10 backup.weekly /path/to/weekly-backup.sh
30 15 backup.monthly /path/to/monthly-backup.sh
Task Schedulers
Using at Command
# Schedule one-time task
echo "/path/to/script.sh" | at 2:30 PM
# Schedule task for specific date
echo "/path/to/script.sh" | at 2:30 PM Dec 25
# List scheduled tasks
atq
# Remove scheduled task
atrm <job_number>
Using batch Command
# Schedule task when system load is low
echo "/path/to/script.sh" | batch
Best Practices
Cron Job Management
Environment Variables
# Set environment in crontab
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
# Add to crontab
0 2 * * * /path/to/script.sh
Logging and Monitoring
#!/bin/bash
# Enhanced logging function
log_message() {
local message="$1"
local log_file="/var/log/cron_jobs.log"
echo "$(date '+%Y-%m-%d %H:%M:%S'): $message" >> "$log_file"
}
# Usage in scripts
log_message "Starting backup process"
# ... backup logic ...
log_message "Backup process completed"
Error Handling
#!/bin/bash
# Script with error handling
set -e # Exit on any error
# Function to handle errors
error_handler() {
echo "Error occurred on line $1"
# Send notification
echo "Cron job failed: $0" | mail -s "Cron Job Alert" admin@example.com
exit 1
}
# Set error trap
trap 'error_handler $LINENO' ERR
# Your script logic here
Security Considerations
File Permissions
# Secure cron job files
chmod 600 /path/to/cronfile
chown root:root /path/to/cronfile
# Secure script files
chmod 700 /path/to/script.sh
chown root:root /path/to/script.sh
Input Validation
#!/bin/bash
# Validate inputs
if [ -z "$1" ]; then
echo "Error: No input provided"
exit 1
fi
# Sanitize inputs
INPUT=$(echo "$1" | tr -d '[:space:]')
Performance Optimization
Resource Management
#!/bin/bash
# Limit resource usage
ulimit -n 1024 # Limit open files
ulimit -u 100 # Limit processes
# Use nice to lower priority
nice -n 10 /path/to/script.sh
Parallel Processing
#!/bin/bash
# Process files in parallel
find /path/to/files -name "*.txt" | xargs -P 4 -I {} process_file {}
Troubleshooting Cron Jobs
Common Issues
Environment Problems
# Check cron environment
# Add to crontab for debugging
* * * * * env > /tmp/cron_env.txt
# Use absolute paths
0 2 * * * /usr/bin/python3 /path/to/script.py
Permission Issues
# Check file permissions
ls -la /path/to/script.sh
# Check cron user
whoami
crontab -l
Debugging Cron Jobs
# Enable cron logging
sudo nano /etc/rsyslog.d/50-default.conf
# Uncomment: cron.* /var/log/cron.log
# Check cron logs
sudo tail -f /var/log/cron.log
Monitoring and Alerts
Health Check Script
#!/bin/bash
# cron_health_check.sh
# Check if cron is running
if ! pgrep -x "cron" > /dev/null; then
echo "WARNING: Cron daemon is not running" | mail -s "Cron Alert" admin@example.com
fi
# Check recent cron job execution
if [ ! -f /var/log/cron.log ]; then
echo "WARNING: Cron log file not found" | mail -s "Cron Alert" admin@example.com
fi
Conclusion
Cron jobs are essential for automating system maintenance and routine tasks. By understanding cron syntax, implementing proper error handling, and following security best practices, you can create reliable automated systems that require minimal manual intervention.
The key to successful cron job implementation is thorough testing, proper logging, and regular monitoring. Modern alternatives like systemd timers and anacron provide additional flexibility for different use cases, but traditional cron remains the most widely used solution for task scheduling on Unix-like systems.