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"
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
That's it. One line per job. If the ping doesn't arrive on schedule, you get alerted.
How it works
- 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"
}'
- Add the ping URL to your cron job:
0 2 * * * /usr/local/bin/backup.sh && curl -s https://cronping.anethoth.com/ping/abc123
- 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:

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"
What's the ugliest monitoring script in your infrastructure? I know you have one. 😄
Top comments (0)