dotlinux guide

Scheduling Jobs with Shell Scripts and Cron: A Comprehensive Guide

Table of Contents

Understanding Cron: The Time-Based Scheduler

Cron is a daemon (background service) that runs continuously on Unix-like systems, executing scheduled tasks (called “cron jobs”) at specified intervals. It reads configuration files called “crontabs” (cron tables) that define when and which commands to run.

Key Components:

  • cron daemon: The background process (cron or crond) that checks crontabs and executes jobs.
  • crontab: A text file containing job schedules. Each user (and the system) can have its own crontab.
  • cron jobs: Individual entries in a crontab that specify a command/script and a schedule.

Cron Syntax Demystified

A crontab entry has the following structure (with 5 or 6 fields, depending on the type of crontab):

# For user crontabs (no user field):
* * * * * command/to/execute

# For system crontabs (e.g., /etc/crontab):
* * * * * user command/to/execute

Time Fields Explained:

The first five fields define the schedule. Here’s what each represents:

FieldRangeDescription
Minute0–59Minute of the hour
Hour0–23Hour of the day (24-hour format)
Day of Month1–31Day of the month
Month1–12 (or Jan–Dec)Month of the year
Day of Week0–6 (0=Sunday, 6=Saturday; or Sun–Sat)Day of the week

Special Characters:

Cron supports special characters to simplify scheduling:

CharacterMeaningExample
*Wildcard (matches all values)* * * * * → Every minute
*/n”Every n units” (step interval)*/15 * * * * → Every 15 minutes
-Range of values10-15 * * * * → Minutes 10–15
,List of values0,15,30,45 * * * * → Every 15 minutes
@Predefined shortcuts (non-standard)@daily → Equivalent to 0 0 * * *

Predefined Shortcuts (@):

Some systems support these for common intervals:

  • @reboot: Run once at system startup
  • @daily/@midnight: 00:00 daily (0 0 * * *)
  • @weekly: Sunday 00:00 (0 0 * * 0)
  • @monthly: 1st of month 00:00 (0 0 1 * *)
  • @yearly/@annually: Jan 1st 00:00 (0 0 1 1 *)

Example Cron Schedules:

# Run at 3:15 AM daily
15 3 * * * /path/to/script.sh

# Run every 30 minutes on weekdays (Mon–Fri)
*/30 * * * 1-5 /path/to/monitor.sh

# Run on the 1st and 15th of every month at 2 PM
0 14 1,15 * * /path/to/report.sh

# Run at 10 PM every Saturday
0 22 * * 6 /path/to/backup.sh

# Run at system startup
@reboot /path/to/startup-script.sh

Creating Effective Shell Scripts for Scheduling

Cron jobs often execute shell scripts, which contain the logic for the task. A well-written script ensures reliability, ease of debugging, and maintainability. Below are key principles for creating scripts intended for cron.

1. Start with a Shebang

Always specify the shell interpreter with a shebang line at the top:

#!/bin/bash

2. Enable Strict Error Handling

Use set options to make the script exit on errors and undefined variables:

#!/bin/bash
set -euo pipefail  # Exit on error, undefined var, or pipe failure
  • -e: Exit immediately if a command fails.
  • -u: Treat undefined variables as errors.
  • -o pipefail: Exit if any command in a pipeline fails.

3. Use Absolute Paths

Cron runs with a minimal environment (e.g., limited PATH). Always use absolute paths for files, commands, and scripts:

# Bad: Relies on PATH
rsync -av /data /backup

# Good: Absolute path
/usr/bin/rsync -av /home/user/data /mnt/backup/daily

4. Log Output

Cron jobs don’t have a terminal, so log output to a file for debugging:

LOG_FILE="/var/log/daily-backup.log"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup started" >> "$LOG_FILE"

5. Define Variables for Reusability

Centralize configurable values (e.g., paths, thresholds) as variables:

SOURCE_DIR="/home/user/documents"
DEST_DIR="/mnt/backup/documents"
RETENTION_DAYS=7  # Keep backups for 7 days

Example: Daily Backup Script

#!/bin/bash
set -euo pipefail

# Configuration
SOURCE_DIR="/home/user/important-files"
DEST_DIR="/mnt/backup/daily"
LOG_FILE="/var/log/daily-backup.log"
RETENTION_DAYS=7

# Log start
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting backup..." >> "$LOG_FILE"

# Create destination if it doesn't exist
mkdir -p "$DEST_DIR" >> "$LOG_FILE" 2>&1

# Perform backup with rsync
/usr/bin/rsync -av --delete "$SOURCE_DIR"/ "$DEST_DIR"/ >> "$LOG_FILE" 2>&1

# Prune old backups (keep last 7 days)
find "$DEST_DIR" -type f -mtime +"$RETENTION_DAYS" -delete >> "$LOG_FILE" 2>&1

# Log completion
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup completed successfully" >> "$LOG_FILE"

Managing Cron Jobs

Editing Crontabs

To manage your user crontab, use the crontab command:

  • crontab -e: Edit your crontab (opens in the default editor, e.g., nano or vim).
  • crontab -l: List your current crontab entries.
  • crontab -r: Delete your crontab (use with caution!).

Example User Crontab Entry

To schedule the backup script above to run daily at 2 AM:

# Edit crontab
crontab -e

# Add this line (then save and exit)
0 2 * * * /home/user/scripts/daily-backup.sh

System-Wide Cron Jobs

For tasks that run as root or affect the entire system, use:

  • /etc/crontab: System-wide crontab with a user field (e.g., 0 3 * * * root /path/to/script.sh).
  • /etc/cron.d/: Directory for custom system crontabs (e.g., /etc/cron.d/backup-job).

Environment Variables in Cron

Cron’s environment is minimal (e.g., PATH=/usr/bin:/bin). To set variables, define them in the crontab or script:

# In crontab: Set PATH and MAILTO
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
MAILTO="[email protected]"  # Send output to this email

0 2 * * * /home/user/scripts/daily-backup.sh

Common Use Cases

1. Log Rotation

Compress and archive old logs to save disk space:

# Cron entry: Run daily at 1 AM
0 1 * * * /usr/local/bin/rotate-logs.sh

2. Database Backups

Dump a MySQL database and upload to cloud storage:

# Cron entry: Run weekly on Sunday at 3 AM
0 3 * * 0 /home/admin/scripts/mysql-backup.sh

3. System Monitoring

Check disk space and alert if usage exceeds 90%:

# Cron entry: Run every 6 hours
0 */6 * * * /usr/local/bin/check-disk-space.sh

4. Cleanup Tasks

Delete temporary files older than 30 days:

# Cron entry: Run monthly on the 1st at midnight
0 0 1 * * /usr/local/bin/cleanup-tmp.sh

Best Practices for Reliable Scheduling

1. Test Scripts Manually First

Always run scripts manually before scheduling them to ensure they work as expected:

bash /home/user/scripts/daily-backup.sh  # Test the backup script

2. Restrict Permissions

  • Make scripts executable but not world-writable:
    chmod 700 /home/user/scripts/daily-backup.sh  # Read/write/execute for owner only
  • Store scripts in a secure directory (e.g., /usr/local/bin for system scripts).

3. Avoid Overloading the System

Schedule resource-intensive jobs (e.g., large backups) during off-peak hours (e.g., midnight–4 AM).

4. Comment Crontabs

Add comments to explain the purpose of each job:

# Daily backup of user documents (2 AM)
0 2 * * * /home/user/scripts/daily-backup.sh

5. Version Control Scripts

Store shell scripts in Git for tracking changes and rollbacks:

git add /home/user/scripts/daily-backup.sh
git commit -m "Add retention policy to backup script"

Troubleshooting Cron Jobs

If a cron job isn’t running as expected, use these steps to diagnose issues:

1. Check if Cron is Running

Ensure the cron daemon is active:

systemctl status cron  # On systemd systems (Ubuntu, Debian)
# or
service crond status  # On SysVinit systems (RHEL, CentOS)

2. Inspect Cron Logs

Cron logs activity to system logs (e.g., /var/log/syslog on Debian/Ubuntu):

grep CRON /var/log/syslog  # Check if the job ran

3. Verify Script Permissions

Ensure the script is executable and the cron user has read access:

ls -l /home/user/scripts/daily-backup.sh  # Should show -rwx------ or similar

4. Debug Script Output

Check the script’s log file for errors:

tail -f /var/log/daily-backup.log  # Monitor the backup log

5. Validate Cron Syntax

Use crontab -l to check for typos, or online tools like Cronitor to validate schedules.

Conclusion

Cron and shell scripts are foundational tools for automating repetitive tasks in Unix-like systems. By mastering cron syntax, writing robust shell scripts, and following best practices (e.g., logging, absolute paths, testing), you can build reliable automation pipelines to save time and reduce errors.

Whether you’re managing a personal server or a enterprise environment, the ability to schedule jobs effectively is a critical skill. Start small—automate a daily backup or log cleanup—and gradually expand to more complex workflows. With practice, you’ll unlock the full potential of cron and shell scripts for seamless system administration.

References