Back to Blog
Tutorial

How to Monitor Cron Jobs: Tools, Techniques, and Best Practices (2025)

Stop wondering if your cron jobs ran. Learn how to monitor execution, get failure alerts, track performance, and ensure your automated tasks run reliably with professional monitoring tools.

14 min read
By Cron Generator Team

Your database backup cron job has been failing silently for 3 weeks. You discover this when you actually need to restore from backup.

Game over.

This scenario plays out constantly in production systems. Cron jobs fail silently. No alerts. No visibility. No accountability. You only discover problems when disaster strikes.

Professional developers don't operate this way.

They monitor every cron job. They get instant alerts when things fail. They track execution history. They measure performance over time.

This guide shows you exactly how to monitor your cron jobs like a pro—from basic logging to sophisticated monitoring platforms that catch failures before they become catastrophes.

The Problem: Silent Failures

Cron jobs are dangerous because they fail silently:

Scenario 1: The Forgotten Backup

0 2 * * * /usr/local/bin/backup-database.sh

What you think happens:

  • ✅ Runs every night at 2 AM
  • ✅ Creates database backup
  • ✅ Everything is protected

What actually happens:

  • ❌ Script has a typo (fails immediately)
  • ❌ No output produced
  • ❌ No alerts sent
  • ❌ You have no backups for months
  • ❌ You discover this when you need to restore

Scenario 2: The Broken PATH

0 3 * * * python /home/user/scripts/process-data.py

Reality:

  • Cron can't find python (not in PATH)
  • Script never runs
  • Data processing stops
  • Business reports are empty
  • Nobody notices for weeks

The Core Problem

Cron doesn't tell you when jobs fail. It runs the command and moves on. No logging. No alerts. No confirmation.

You need monitoring.

Level 1: Basic Logging (Better Than Nothing)

The absolute minimum: redirect output to a log file.

Simple Output Logging

0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

What this does:

  • >> appends output to log file
  • 2>&1 captures errors too
  • Every execution leaves a record

Check logs manually:

tail -f /var/log/backup.log

Timestamped Logging

Better: add timestamps to your scripts.

#!/bin/bash
# File: /usr/local/bin/backup.sh

LOG_FILE="/var/log/backup.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

log "Starting backup..."

if /usr/bin/mysqldump mydb > /backups/db.sql; then
    log "SUCCESS: Backup completed"
else
    log "ERROR: Backup failed"
    exit 1
fi

log "Backup finished"

Cron entry:

0 2 * * * /usr/local/bin/backup.sh

Output in log:

[2025-01-16 02:00:01] Starting backup...
[2025-01-16 02:03:47] SUCCESS: Backup completed
[2025-01-16 02:03:47] Backup finished

Pros:

  • ✅ Simple to implement
  • ✅ No external dependencies
  • ✅ Searchable history

Cons:

  • ❌ Must manually check logs
  • ❌ No alerts on failure
  • ❌ Logs can grow huge
  • ❌ Easy to ignore/forget

Level 2: Email Notifications on Failure

Get notified when something breaks.

Cron's Built-in Email (If Configured)

Set MAILTO in your crontab:

MAILTO=admin@example.com

0 2 * * * /usr/local/bin/backup.sh

If the job produces output, cron emails it to you.

Problems:

  • Most servers don't have mail configured
  • You get email for EVERY execution (spam)
  • Hard to distinguish success from failure

Better: Only Email on Failure

0 2 * * * /usr/local/bin/backup.sh || echo "Backup failed!" | mail -s "BACKUP FAILURE" admin@example.com

How it works:

  • || means "if previous command fails, run this"
  • Only sends email when backup returns non-zero exit code

Email with Details

#!/bin/bash
# File: /usr/local/bin/backup-with-email.sh

EMAIL="admin@example.com"
LOG_FILE="/var/log/backup.log"

# Run backup
if /usr/local/bin/backup.sh >> "$LOG_FILE" 2>&1; then
    # Success - do nothing
    exit 0
else
    # Failure - send email with logs
    cat "$LOG_FILE" | mail -s "BACKUP FAILED on $(hostname)" "$EMAIL"
    exit 1
fi

Pros:

  • ✅ Automatic alerts
  • ✅ Only emails on failures
  • ✅ No external services needed

Cons:

  • ❌ Requires mail server setup
  • ❌ Email can be delayed
  • ❌ No history/dashboard
  • ❌ Can't track trends

Level 3: Dead Man's Switch Monitoring

The professional approach: heartbeat monitoring.

How It Works

  1. Your cron job makes an HTTP request when it SUCCEEDS
  2. Monitoring service expects regular heartbeats
  3. If heartbeat stops, you get alerted

This catches two failure modes:

  • Script fails (doesn't send heartbeat)
  • Script doesn't run at all (missing heartbeat)

Using Cronitor (Recommended)

Step 1: Set up a monitor at cronitor.io

Create a monitor with expected schedule (e.g., "daily at 2 AM").

Step 2: Get your unique ping URL:

https://cronitor.link/p/abc123xyz/backup-job

Step 3: Modify your script to ping on success:

#!/bin/bash
# File: /usr/local/bin/monitored-backup.sh

CRONITOR_URL="https://cronitor.link/p/abc123xyz/backup-job"

# Run backup
if /usr/bin/mysqldump mydb | gzip > /backups/db_$(date +%Y%m%d).sql.gz; then
    # Success - send heartbeat
    curl -fsS -m 10 --retry 5 "$CRONITOR_URL"
else
    # Failure - ping failure endpoint
    curl -fsS -m 10 --retry 5 "$CRONITOR_URL/fail"
    exit 1
fi

What Cronitor monitors:

  • ✅ Did the job run on schedule?
  • ✅ Did it succeed or fail?
  • ✅ How long did it take?
  • ✅ Any missing executions?

Alerts:

  • Email
  • SMS
  • Slack
  • PagerDuty
  • Webhooks

Using Healthchecks.io (Free Alternative)

Similar concept, free for personal use:

#!/bin/bash
HEALTHCHECK_URL="https://hc-ping.com/your-uuid-here"

# Ping start
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL/start"

# Run your job
if /usr/local/bin/backup.sh; then
    # Ping success
    curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL"
else
    # Ping failure
    curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL/fail"
fi

Benefits:

  • ✅ Free for up to 20 checks
  • ✅ Email and Slack alerts
  • ✅ Simple dashboard
  • ✅ No credit card required

Level 4: Execution Tracking and Metrics

Track performance over time.

Log Execution Duration

#!/bin/bash
# File: /usr/local/bin/timed-backup.sh

LOG_FILE="/var/log/backup-metrics.log"
START_TIME=$(date +%s)

# Run backup
/usr/local/bin/backup.sh

END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

echo "$(date '+%Y-%m-%d %H:%M:%S'),SUCCESS,$DURATION" >> "$LOG_FILE"

Output:

2025-01-16 02:00:00,SUCCESS,187
2025-01-17 02:00:00,SUCCESS,192
2025-01-18 02:00:00,SUCCESS,245

Analyze trends:

# Average backup time
awk -F, '{sum+=$3; count++} END {print sum/count}' /var/log/backup-metrics.log

# Slowest backup
awk -F, '{print $3,$1}' /var/log/backup-metrics.log | sort -rn | head -1

Database Logging

Store execution history in a database for better analytics:

#!/bin/bash
# File: /usr/local/bin/db-logged-backup.sh

START_TIME=$(date +%s)
START_DATE=$(date '+%Y-%m-%d %H:%M:%S')

# Run backup
if /usr/local/bin/backup.sh; then
    STATUS="success"
    EXIT_CODE=0
else
    STATUS="failed"
    EXIT_CODE=$?
fi

END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# Log to database
mysql -u logger -p'password' monitoring <<EOF
INSERT INTO cron_executions (job_name, start_time, duration, status, exit_code)
VALUES ('backup', '$START_DATE', $DURATION, '$STATUS', $EXIT_CODE);
EOF

Query execution history:

-- Recent executions
SELECT * FROM cron_executions 
WHERE job_name = 'backup' 
ORDER BY start_time DESC 
LIMIT 10;

-- Success rate last 30 days
SELECT 
    COUNT(*) as total,
    SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as successes,
    ROUND(100.0 * SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) / COUNT(*), 2) as success_rate
FROM cron_executions
WHERE job_name = 'backup' 
AND start_time > DATE_SUB(NOW(), INTERVAL 30 DAY);

Level 5: Comprehensive Monitoring Platform

For production systems with many cron jobs.

Monitoring multiple jobs:

Features:

  • Monitor unlimited cron jobs
  • Execution history dashboard
  • Performance metrics
  • Uptime monitoring
  • Error rate tracking
  • Team notifications
  • Incident management
  • Status pages

Monitoring multiple jobs:

# Each job pings unique URL
0 2 * * * /usr/local/bin/backup.sh && curl https://cronitor.link/p/abc123/backup
0 3 * * * /usr/local/bin/cleanup.sh && curl https://cronitor.link/p/abc123/cleanup
0 4 * * * /usr/local/bin/reports.sh && curl https://cronitor.link/p/abc123/reports

Dashboard shows:

  • Which jobs ran successfully
  • Which failed
  • Which didn't run at all
  • Execution duration trends
  • Historical reliability

Better Uptime (Alternative)

Similar features with phone call alerts:

Unique feature: Calls your phone if critical jobs fail (not just email/SMS).

Setup:

# Heartbeat monitoring
0 2 * * * /usr/local/bin/critical-backup.sh && curl https://betteruptime.com/api/v1/heartbeat/your-token

Alert escalation:

  1. Email immediately
  2. SMS after 5 minutes
  3. Phone call after 10 minutes
  4. Alert backup contacts after 15 minutes

Monitoring Best Practices

1. Monitor Critical Jobs First

Don't try to monitor everything at once.

Start with:

  • Database backups
  • Data synchronization
  • Financial calculations
  • Security scans
  • Customer-facing features

Add others gradually.

2. Set Realistic Expectations

Cronitor/Healthchecks need to know when to expect heartbeats.

Daily at 2 AM → Grace period: 15 minutes
Every 5 minutes → Grace period: 2 minutes
Weekly on Sunday → Grace period: 4 hours

If job doesn't ping within grace period, you get alerted.

3. Alert the Right People

Not every failure needs to wake someone up at 3 AM.

Severity levels:

  • Critical: Database backups, financial processing → Phone call
  • High: Data sync, reports → SMS
  • Medium: Cache clearing, logs → Email
  • Low: Cleanup tasks → Dashboard only

4. Test Your Monitoring

Verify alerts actually work:

# Trigger a test failure
0 2 * * * /usr/local/bin/backup.sh && curl https://cronitor.link/abc123/backup/fail

Check that:

  • Alert email arrives
  • Alert has useful information
  • Alert reaches right people
  • Escalation works

5. Review Execution History

Set up weekly reviews:

# Weekly report of all cron failures
0 9 * * 1 /usr/local/bin/weekly-cron-report.sh

Look for patterns:

  • Jobs failing consistently?
  • Increasing execution time?
  • Missed executions?
  • New errors?

Complete Monitoring Setup Example

Here's a production-ready monitored cron job:

#!/bin/bash
# File: /usr/local/bin/production-backup.sh

set -euo pipefail

# Configuration
BACKUP_DIR="/backups/mysql"
LOG_FILE="/var/log/backup.log"
CRONITOR_URL="https://cronitor.link/p/abc123/backup"
ALERT_EMAIL="ops@example.com"
DB_NAME="production"

# Logging function
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

# Start monitoring
START_TIME=$(date +%s)
log "Starting backup for $DB_NAME"
curl -fsS -m 10 "$CRONITOR_URL/run" || true

# Check disk space
AVAILABLE=$(df /backups | tail -1 | awk '{print $4}')
if [ "$AVAILABLE" -lt 10485760 ]; then
    log "ERROR: Low disk space"
    curl -fsS "$CRONITOR_URL/fail?msg=Low+disk+space" || true
    echo "Low disk space: ${AVAILABLE}KB" | mail -s "BACKUP ALERT" "$ALERT_EMAIL"
    exit 1
fi

# Run backup
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_$(date +%Y%m%d_%H%M%S).sql.gz"

if mysqldump --single-transaction "$DB_NAME" | gzip > "$BACKUP_FILE"; then
    # Verify backup
    if [ -s "$BACKUP_FILE" ]; then
        SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
        log "SUCCESS: Backup completed ($SIZE)"
        
        # Cleanup old backups (keep 7 days)
        find "$BACKUP_DIR" -name "${DB_NAME}_*.sql.gz" -mtime +7 -delete
        log "Cleaned up old backups"
        
        # Report success
        END_TIME=$(date +%s)
        DURATION=$((END_TIME - START_TIME))
        curl -fsS "$CRONITOR_URL?duration=$DURATION" || true
        
        exit 0
    else
        log "ERROR: Backup file is empty"
        curl -fsS "$CRONITOR_URL/fail?msg=Empty+backup" || true
        exit 1
    fi
else
    log "ERROR: mysqldump failed"
    curl -fsS "$CRONITOR_URL/fail?msg=mysqldump+failed" || true
    tail -20 "$LOG_FILE" | mail -s "BACKUP FAILED" "$ALERT_EMAIL"
    exit 1
fi

Cron entry:

MAILTO=ops@example.com

0 2 * * * /usr/local/bin/production-backup.sh

This setup provides:

  • ✅ Detailed logging with timestamps
  • ✅ Disk space checks before backup
  • ✅ Backup verification
  • ✅ Automatic cleanup of old backups
  • ✅ Heartbeat monitoring (Cronitor)
  • ✅ Email alerts on failure
  • ✅ Duration tracking
  • ✅ Error messages in alerts

Monitoring Checklist

Before deploying any critical cron job:

  • [ ] Logging with timestamps enabled
  • [ ] Log rotation configured
  • [ ] Exit codes properly set (0=success, non-zero=failure)
  • [ ] Heartbeat monitoring configured
  • [ ] Alert contacts defined
  • [ ] Alert severity set appropriately
  • [ ] Test failure scenario works
  • [ ] Dashboard shows execution history
  • [ ] Grace periods set correctly
  • [ ] Documentation updated

Conclusion: Never Fly Blind Again

The problem: Cron jobs fail silently. You discover issues weeks later when you need the data.

The solution: Monitor everything.

Levels of monitoring:

  1. Basic: Log files with timestamps
  2. Better: Email notifications on failure
  3. Good: Heartbeat monitoring (Cronitor/Healthchecks)
  4. Best: Full monitoring platform with metrics

Your next steps:

  1. Add logging to all cron jobs (at minimum)
  2. Set up heartbeat monitoring for critical jobs (Cronitor/Healthchecks)
  3. Configure alerts to the right people
  4. Test your monitoring by triggering failures
  5. Review dashboards weekly

Professional monitoring transforms:

| Without Monitoring | With Monitoring | |-------------------|-----------------| | "Did backup run?" → "No idea" | "Yes, 187 seconds, 100% success rate" | | "When did it fail?" → "Unknown" | "First failure: Jan 3 at 2:13 AM" | | "How often?" → "Can't tell" | "14 successes, 1 failure (93% uptime)" | | Discovery time → Weeks later | Alert → 30 seconds |

Stop wondering. Start monitoring.

Ready to create reliable cron schedules? Use our Cron Expression Generator to build perfect schedules, then monitor them with Cronitor!


Related Articles

Monitoring & Logging:

Production Best Practices:

Fundamentals:


Keywords: cron job monitoring, monitor cron jobs, cron job alerts, cron job notifications, cronitor alternative, healthchecks cron, cron job logging, cron monitoring tools, cron heartbeat monitoring