DEV Community

Jack
Jack

Posted on • Originally published at anethoth.com

I Replaced My 47-Line Bash Monitoring Script with One curl Command

Every DevOps engineer has that bash script. The one monitoring cron jobs. The one nobody wants to touch.

Here was mine:

#!/bin/bash
# cron_monitor.sh - "temporary" script from 2019

LOCK_FILE="/tmp/backup_monitor.lock"
LOG_FILE="/var/log/cron_monitor.log"
LAST_RUN_FILE="/tmp/last_backup_run"
SLACK_WEBHOOK="https://hooks.slack.com/services/T.../B.../xxx"
MAX_AGE=7200  # 2 hours

if [ -f "$LOCK_FILE" ]; then
    echo "$(date) Lock file exists, skipping" >> $LOG_FILE
    exit 0
fi

touch "$LOCK_FILE"

if [ ! -f "$LAST_RUN_FILE" ]; then
    echo "$(date) No last run file found" >> $LOG_FILE
    curl -s -X POST "$SLACK_WEBHOOK" -d '
    {"text": "⚠️ Backup monitor: no last run file"}' 
    rm -f "$LOCK_FILE"
    exit 1
fi

LAST_RUN=$(cat "$LAST_RUN_FILE")
NOW=$(date +%s)
AGE=$(( NOW - LAST_RUN ))

if [ "$AGE" -gt "$MAX_AGE" ]; then
    HOURS=$(( AGE / 3600 ))
    curl -s -X POST "$SLACK_WEBHOOK" -d '
    {"text": "🚨 Backup job missed! Last run ''''$HOURS hours ago"}' 
    echo "$(date) ALERT: backup missed, age=$AGE" >> $LOG_FILE
fi

rm -f "$LOCK_FILE"
Enter fullscreen mode Exit fullscreen mode

47 lines. Race conditions. A lock file that sometimes doesn't get cleaned up. Slack formatting that breaks if the message has special characters. And it only monitors ONE job.

The replacement

# In your crontab, add this to the end of each job:
0 */2 * * * /usr/local/bin/backup.sh && curl -s https://cronping.anethoth.com/ping/YOUR_TOKEN
Enter fullscreen mode Exit fullscreen mode

That's it. One line per job. If the ping doesn't arrive on schedule, you get alerted.

How it works

  1. Create a monitor with your expected schedule:
curl -X POST https://cronping.anethoth.com/api/v1/monitors   -H "X-API-Key: YOUR_KEY"   -H "Content-Type: application/json"   -d '{
    "name": "nightly-backup",
    "schedule": "0 2 * * *",
    "grace_period": 300,
    "alert_webhook": "https://hooks.slack.com/services/YOUR/WEBHOOK"
  }'
Enter fullscreen mode Exit fullscreen mode
  1. Add the ping URL to your cron job:
0 2 * * * /usr/local/bin/backup.sh && curl -s https://cronping.anethoth.com/ping/abc123
Enter fullscreen mode Exit fullscreen mode
  1. If your job fails (non-zero exit) or doesn't run, the never fires, and you get alerted after the grace period.

What I got back

  • No more lock files. The monitoring service is stateless from your end.
  • No more log parsing. The dashboard shows ping history, uptime, and timing.
  • Multi-job monitoring. Each job gets its own monitor, its own schedule, its own alerts.
  • Status badges you can embed in your README:
![Backup Status](https://cronping.anethoth.com/badge/YOUR_TOKEN)
Enter fullscreen mode Exit fullscreen mode

Free tier

CronPing gives you 3 monitors for free. No credit card. Enough to cover your most critical jobs.

You can also validate cron expressions programmatically:

# What does this expression actually mean?
curl "https://cronping.anethoth.com/api/v1/cron/describe?expr=*/15+*+*+*+1-5"
# {"description": "Every 15 minutes, Monday through Friday", ...}

# When does it run next?
curl "https://cronping.anethoth.com/api/v1/cron/next?expr=0+2+*+*+*&count=5"
Enter fullscreen mode Exit fullscreen mode

What's the ugliest monitoring script in your infrastructure? I know you have one. 😄

Top comments (0)