Cron Job Monitoring: Stop Silent Failures Fast
The most effective form of cron job monitoring is the heartbeat check: your job pings a monitoring service every time it completes successfully, and the service alerts you when an expected ping doesn't arrive. One extra command in your crontab is all it takes:
*/10 * * * * /home/user/scripts/task.sh && curl -fsS -m 10 https://hc-ping.com/your-uuid-here > /dev/null
If the script fails, the && prevents the ping; if the whole server dies, no ping arrives either. Both cases trigger a cron failure alert. This pattern — often called a dead man's switch — is the foundation of every serious cron monitoring setup, and this guide shows you how to build it.
Why Cron Jobs Fail Silently
Cron has no built-in alerting worth relying on. Understand its defaults and the problem becomes obvious:
- Cron only reports output, not outcomes. It emails whatever a job prints — but a well-behaved quiet script that fails with no output triggers nothing.
- The email path is usually broken anyway. Local mail delivery is unconfigured on most modern servers, so even those messages go nowhere.
- Nothing checks that jobs run at all. If the crontab is accidentally wiped, the daemon stops, or the server is down at the scheduled minute, cron itself will never tell you.
The result is a familiar horror story: the nightly backup that "ran fine" for months turns out to have died in March, discovered only when someone needs a restore in July. That's the exact gap that monitoring cron jobs closes.
The Dead Man's Switch Pattern
Traditional monitoring asks "is something bad happening?" A dead man's switch inverts it: "has the expected good thing stopped happening?" That inversion is what makes it catch failure modes ordinary alerting misses — crashed servers, deleted crontabs, hung scripts — because all of them look the same: silence.
The mechanics:
- Register each job with a monitoring service and get a unique ping URL.
- Tell the service the expected schedule (every 10 minutes, daily at 02:00…) and a grace period.
- Append a ping to the job that fires only on success.
- The service alerts you — email, Slack, SMS, PagerDuty — when a ping is late or missing.
The crontab entry, dissected:
0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 https://hc-ping.com/your-uuid > /dev/null
&&— ping only ifbackup.shexited 0. Failure = no ping = alert.-f— treat HTTP errors as failures rather than success.-sS— silent, but still show real errors.-m 10— cap the ping at 10 seconds so monitoring never hangs your job.--retry 3— ride out transient network blips.
Some services also accept a /fail endpoint you can hit explicitly on error, plus a /start ping for measuring runtime — useful for jobs where "took 4 hours instead of 10 minutes" is itself a failure.
Your Monitoring Options Compared
| Approach | Examples | Best for | Trade-off |
|---|---|---|---|
| Hosted heartbeat service | Healthchecks.io, Cronitor, Dead Man's Snitch | Most teams; fastest setup | Depends on external service |
| Self-hosted heartbeat | Healthchecks (open source) | Privacy/compliance needs | You maintain the monitor |
| Metrics stack | Prometheus Pushgateway + Alertmanager | Teams already on Prometheus | Real configuration effort |
| DIY scripts | Log checks, wrapper scripts | Zero budget, tiny setups | You're monitoring the monitor |
A few honest notes on each:
- Hosted services are the pragmatic default. Healthchecks.io is notable for being fully open source with a free hosted tier; Cronitor and Dead Man's Snitch are established commercial options. All follow the same ping model, so switching later is cheap.
- Self-hosting Healthchecks gives you the same features on your own infrastructure — just don't run the monitor on the same server as the jobs it watches, or one outage silences both.
- Prometheus-based setups fit teams with existing dashboards and on-call rotations: jobs push a completion timestamp to Pushgateway, and an alert rule fires when the timestamp goes stale.
- DIY (a second cron job that greps logs, a wrapper that emails on non-zero exit) is better than nothing, but it inherits cron's own blind spots — if the server dies, your watchdog dies with it.
Best Practices for Monitoring Cron Jobs
- Ping on success only. Chain with
&&, never;— a semicolon pings even when the job failed, which defeats the entire mechanism. - Set grace periods thoughtfully. A nightly backup that normally takes 20 minutes deserves maybe a 1-hour grace window — tight enough to matter, loose enough to avoid false alarms.
- Monitor the important jobs first. Backups, billing, certificate renewals, data syncs. A missed cache-warm doesn't need to page anyone.
- Route alerts where people look. An alert to an unread inbox is a silent failure with extra steps. Use Slack or your paging tool for critical jobs.
- Keep logging too. Monitoring tells you that a job failed; the log (
>> /var/log/job.log 2>&1) tells you why.
Common Mistakes
- Using
;instead of&&before the ping — the number one way to build monitoring that never alerts. - No timeout on the ping. Without
-m 10, a hung monitoring endpoint can hang your job. - Alert fatigue by over-monitoring. Twenty noisy checks train everyone to ignore the one that matters.
- Monitoring from the same box. A watchdog on the monitored server shares its fate.
- Never testing the alert. Disable a test job once and confirm a real notification arrives — before you're relying on it.
Conclusion
Cron job monitoring boils down to one idea: make every important job prove it ran, and treat silence as failure. The dead man's switch pattern implements this with a single appended command — && curl -fsS -m 10 https://ping-url > /dev/null — and a service that alerts when the ping goes missing. Start with your backups tonight: register one check, add one ping, and the era of discovering three-month-old failures is over.
If a check just alerted you and now you need to find out why the job died, our cron troubleshooting guide walks the diagnosis step by step.
Frequently Asked Questions
How do I monitor if a cron job ran successfully?
Append a success-gated ping to the job: command && curl -fsS https://your-ping-url. A heartbeat service expecting that ping on schedule alerts you whenever it fails to arrive — covering script failures, cron misconfiguration, and dead servers alike.
What is a dead man's switch in monitoring?
It's monitoring by expected silence-breaking: the system must regularly check in, and the absence of a check-in triggers the alarm. For cron, each successful run sends a ping; a missing ping means the job failed, hung, or never started.
Are there free cron job monitoring tools?
Yes. Healthchecks.io offers a free hosted tier and is fully open source if you'd rather self-host it. Several commercial tools like Cronitor also provide free plans for a small number of monitors.
Why doesn't cron email me when a job fails?
Cron emails captured output, not failures — a job that fails silently sends nothing, and a job that succeeds noisily sends mail anyway. On top of that, most modern servers have no working local mail delivery, so even generated messages are lost.
Need the expression itself? Build and test any cron schedule in our free visual generator — with live upcoming-run previews in Unix and Quartz formats.
Related guides
References
- Healthchecks.io documentation — the ping API and open-source self-hosting guide
- curl manual — the -f, -sS, -m, and --retry flags used in heartbeat pings
- Prometheus Pushgateway — the metrics-stack approach to batch job monitoring