Script Scheduling with Cron: The Complete Guide

Master Linux's built-in job scheduler to automate script execution at precise intervals. This comprehensive guide covers cron syntax, scheduling patterns, error handling, and best practices for production-ready automation.

Understanding Cron: Linux's Time-Based Job Scheduler

Cron is a time-based job scheduler in Unix-like operating systems. It enables you to schedule jobs (commands or scripts) to run periodically at fixed times, dates, or intervals. Cron is ideal for:

  • Automated backups: Daily, weekly, or monthly data protection
  • System maintenance: Regular cleanup and optimization tasks
  • Monitoring scripts: Periodic health checks and alerts
  • Data processing: Scheduled ETL jobs and reports
  • Application tasks: Cache clearing, session cleanup, etc.

1. Cron Syntax: The Five Fields Explained

Minute
0 - 59
Hour
0 - 23
Day of Month
1 - 31
Month
1 - 12
Day of Week
0 - 7 (0 or 7 = Sunday)
COMMAND TO EXECUTE

Special Characters Reference

*
Wildcard: Matches any value
* * * * * = Every minute
,
Value List Separator: Specify multiple values
0,15,30,45 * * * * = Every 15 minutes
-
Range: Specify a range of values
0 9-17 * * 1-5 = Every hour from 9 AM to 5 PM, weekdays
/
Step Values: Specify increments
*/10 * * * * = Every 10 minutes

2. Practical Cron Examples

0 2 * * *
Daily at 2:00 AM
Perfect for nightly backups when system usage is low
*/15 * * * *
Every 15 minutes
Service monitoring and health checks
0 0 * * 0
Weekly on Sunday at midnight
Weekly maintenance and reporting
0 9-17 * * 1-5
Every hour from 9 AM to 5 PM, weekdays
Business-hour monitoring or processing
0 0 1 * *
Monthly on the 1st at midnight
Monthly archiving and billing tasks
0 12 1 1 *
Annually on Jan 1 at noon
Yearly reports and license renewals

3. Managing Crontab Files

Cron jobs are managed through crontab (cron table) files. Each user has their own crontab, and there's also a system-wide crontab.

User Crontab Commands

# Edit your personal crontab
crontab -e

# View your current crontab
crontab -l

# Remove all your cron jobs
crontab -r

# List another user's crontab (requires sudo)
sudo crontab -u username -l

System Crontab Files

# System-wide crontab (requires root)
/etc/crontab

# Directory for scripts that run hourly, daily, weekly, monthly
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/

# Additional cron configuration files
/etc/cron.d/
User vs System Crontab:
User crontab (crontab -e): Runs as the user who owns it
System crontab (/etc/crontab): Can specify which user runs each job
cron.d directory: For packages to install cron jobs without editing system crontab
Predefined directories: Drop scripts in cron.daily/, cron.hourly/, etc.

4. Production-Ready Crontab Template

# ================= SYSTEM MAINTENANCE =================
# Backup important directories daily at 2 AM
0 2 * * * /usr/local/bin/backup-files.sh >> /var/log/backup.log 2>&1

# Update system packages every Sunday at 3 AM
0 3 * * 0 /usr/local/bin/update-system.sh >> /var/log/updates.log 2>&1

# Cleanup temporary files daily at 4 AM
0 4 * * * /usr/local/bin/cleanup-temp.sh >> /var/log/cleanup.log 2>&1

# ================= MONITORING & ALERTS =================
# System health check every 30 minutes
*/30 * * * * /usr/local/bin/health-check.sh >> /var/log/health.log 2>&1

# Disk space monitoring every hour
0 * * * * /usr/local/bin/check-disk.sh >> /var/log/disk.log 2>&1

# Service monitoring every 5 minutes
*/5 * * * * /usr/local/bin/monitor-services.sh >> /var/log/services.log 2>&1

# ================= APPLICATION TASKS =================
# Database backup daily at 1 AM
0 1 * * * /usr/local/bin/backup-db.sh >> /var/log/db-backup.log 2>&1

# Log rotation daily at midnight
0 0 * * * /usr/local/bin/rotate-logs.sh >> /var/log/rotation.log 2>&1

# Cache clearing every 6 hours
0 */6 * * * /usr/local/bin/clear-cache.sh >> /var/log/cache.log 2>&1

# ================= CUSTOM SCHEDULES =================
# Business hours only (9 AM - 5 PM, weekdays)
0 9-17 * * 1-5 /usr/local/bin/business-process.sh >> /var/log/business.log 2>&1

# Every 10 minutes during working hours
*/10 9-17 * * 1-5 /usr/local/bin/monitor-production.sh >> /var/log/prod-monitor.log 2>&1

# Weekend maintenance
0 2 * * 6 /usr/local/bin/weekend-maintenance.sh >> /var/log/weekend.log 2>&1

5. Advanced Cron Techniques

Preventing Overlapping Jobs

#!/bin/bash
# Using flock to prevent overlapping executions
# create-lock.sh

LOCK_FILE="/tmp/my-script.lock"
TIMEOUT=300  # 5 minutes

# Use flock to acquire lock with timeout
if flock -n -x -w $TIMEOUT 200; then
    echo "Lock acquired, starting execution..."
    
    # Your script logic here
    sleep 60  # Simulate work
    
    echo "Execution completed"
    
    # Lock is automatically released when script ends
else
    echo "Another instance is already running or lock timeout"
    exit 1
fi 200>$LOCK_FILE

Environment Variables in Cron

# Cron has minimal environment by default
# Always set PATH and other variables at the top of your crontab

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/home/youruser
LOGNAME=youruser

# Also set variables in your scripts
#!/bin/bash
source /home/youruser/.bashrc  # If needed
export MY_VAR="value"

# Better: Set critical variables explicitly
BACKUP_DIR="/backups"
LOG_FILE="/var/log/my-script.log"

Error Handling and Notifications

#!/bin/bash
# error-handling.sh - Cron job with proper error handling

# Configuration
SCRIPT_NAME=$(basename "$0")
LOG_FILE="/var/log/${SCRIPT_NAME}.log"
ERROR_LOG="/var/log/${SCRIPT_NAME}_errors.log"
ADMIN_EMAIL="admin@example.com"

# Redirect all output
exec >> "$LOG_FILE" 2>> "$ERROR_LOG"

# Function to send alert email
send_alert() {
    local subject="$1"
    local message="$2"
    
    echo "$message" | mail -s "$subject" "$ADMIN_EMAIL"
    echo "[$(date)] Alert sent: $subject" >> "$LOG_FILE"
}

# Trap errors
trap 'send_alert "CRON ERROR: $SCRIPT_NAME failed" "Script failed at $(date)"; exit 1' ERR

# Start execution
echo "=== Starting $SCRIPT_NAME at $(date) ==="

# Your main logic here
# Example: Backup database
if ! mysqldump -u root database > /backups/db.sql; then
    echo "ERROR: Database backup failed"
    send_alert "Database Backup Failed" "Check $ERROR_LOG for details"
    exit 1
fi

echo "=== Completed successfully at $(date) ==="

6. Cron Best Practices

Practice Why It Matters Implementation Use Absolute Paths Cron jobs run with minimal PATH environment /usr/local/bin/my-script.sh not my-script.sh Redirect Output Cron output goes to email; capture it for debugging >> /var/log/script.log 2>&1 Test Before Scheduling Ensure script works correctly in cron environment Run with env -i /path/to/script.sh to simulate cron Use Locking Prevent overlapping executions of long-running jobs flock -n /tmp/script.lock /path/to/script.sh Set Environment Variables Cron doesn't load your shell's environment Set PATH, HOME, etc. at top of crontab Monitor Cron Logs Debug failed jobs and monitor execution Check /var/log/cron.log or /var/log/syslog

Cron Job Checklist

  • Does the script use absolute paths for all commands?
  • Are all necessary environment variables set?
  • Is output redirected to log files?
  • Does the script handle errors gracefully?
  • Have you tested with minimal environment?
  • Is there locking for long-running jobs?
  • Are permissions correctly set?
  • Have you documented what the job does?

7. Common Cron Problems & Solutions

Problem: Script Works Manually but Not in Cron

Solution: Test with minimal environment:
env -i /path/to/script.sh

Check environment variables and PATH settings.

Problem: No Output or Logging

Solution: Always redirect output:
*/5 * * * * /script.sh >> /var/log/script.log 2>&1

Check mail for cron output: mail

Problem: Overlapping Executions

Solution: Use file locking:
flock -n /tmp/script.lock /script.sh

Or check for existing process with pgrep.

Problem: Permission Denied

Solution: Ensure script is executable:
chmod +x /path/to/script.sh

Check user permissions and sudo requirements.

8. Alternative Scheduling Tools

Tool Best For When to Choose Over Cron systemd Timers Modern Linux systems with systemd Complex dependencies, socket activation, better logging at One-time future jobs Single execution at specific time instead of recurring anacron Desktops and laptops that may be off Missed jobs when system is powered off Celery Python applications, distributed tasks Complex workflows, message queues, distributed systems Airflow Complex workflows, data pipelines DAGs, monitoring UI, complex dependencies

Systemd Timer Example

# /etc/systemd/system/backup.service
[Unit]
Description=Daily Backup Service
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=backupuser
Group=backupuser

# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

# Enable and start
sudo systemctl enable backup.timer
sudo systemctl start backup.timer
sudo systemctl list-timers  # View all timers
Cron Security Considerations:
1. Limit cron access: Use /etc/cron.allow and /etc/cron.deny
2. Avoid root cron: Use specific users with minimal privileges
3. Secure credentials: Don't store passwords in scripts; use config files or environment
4. Monitor cron logs: Watch for unauthorized cron job additions
5. Validate inputs: If scripts process external data, validate and sanitize
6. Use secure permissions: chmod 600 for crontab files
7. Regular audits: Review all cron jobs periodically

Getting Started with Cron

Follow this step-by-step guide to schedule your first script:

  1. Write your script: Ensure it uses absolute paths and handles errors
  2. Test manually: Run the script from command line
  3. Test in cron environment: Use env -i /path/to/script.sh
  4. Add logging: Redirect output to a log file
  5. Edit crontab: Run crontab -e
  6. Add your job: Use proper cron syntax
  7. Monitor execution: Check logs and system mail
  8. Iterate and improve: Add error handling, notifications, locking

Master Cron for Reliable Automation

Cron is a powerful tool that, when used correctly, provides rock-solid automation for repetitive tasks. Start with simple schedules and gradually implement best practices like logging, error handling, and locking.

Remember: The most important cron job is the one that monitors your other cron jobs. Always implement monitoring and alerting for critical automated tasks.

Next Steps: Schedule one non-critical script using the patterns in this guide. Monitor it for a week, then add more sophisticated features like error notifications and locking mechanisms.