Back to blog
cron monitoring tutorial

How to monitor cron jobs and get alerted when one fails

Cron runs your job and forgets about it. Here is a practical way to monitor cron jobs, catch silent failures, and get an alert the moment one stops running.

The Cronaut team

Cron is great at starting jobs and terrible at telling you when one breaks. It runs your script on schedule, throws away the output unless you capture it, and never checks whether the job did what it was supposed to. If a backup, a billing sync or a cleanup task stops working, you usually find out days later when something downstream is missing.

This guide covers the practical ways to monitor cron jobs, from the built-in basics to a heartbeat approach that catches the failure most setups miss.

What “monitoring a cron job” actually means

There are three different failures, and they need different handling:

  1. The job ran and errored. It exited non-zero, threw a stack trace, or printed an error.
  2. The job ran but did the wrong thing. It exited zero but produced no output, or partial output, because of a silent bug.
  3. The job never ran at all. A bad deploy dropped the crontab entry, the server was down, or the schedule was wrong.

Most people only guard against the first one. The third is the dangerous one, because there is no error to catch and nothing to log.

The built-in option: capture output and exit codes

Cron emails the output of a job to the user’s local mailbox if MAILTO is set and a mailer is installed. At the top of your crontab:

MAILTO=you@example.com
0 2 * * *  /usr/local/bin/backup.sh

If the job prints to stderr or exits non-zero, you get mail. This works, but it has real limits. It depends on a working local mail setup, it floods you with noise from chatty jobs, and it tells you nothing when the job does not run, because there is no output to send.

A small improvement is to log explicitly and check the exit code yourself:

0 2 * * *  /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1 || echo "backup failed" | mail -s "backup failed" you@example.com

You now have a log and an alert on failure. You still have no alert when the line never runs.

The fix: heartbeat monitoring

Heartbeat monitoring flips the logic around. Instead of waiting for the job to report a failure, you wait for it to report success, and you alert when that success does not arrive on time. The job pings a URL when it finishes:

0 2 * * *  /usr/local/bin/backup.sh && curl -fsS https://ping.cronaut.dev/your-check-id

The && matters. The ping only fires if backup.sh exits zero, so a failed run sends no ping, and a missing crontab entry sends no ping either. Either way the expected signal does not arrive, and that absence is what gets caught.

For more detail, signal the three states separately:

curl -fsS https://ping.cronaut.dev/your-check-id/start
backup.sh && curl -fsS https://ping.cronaut.dev/your-check-id   # success
# on failure:
curl -fsS https://ping.cronaut.dev/your-check-id/fail

Now you can see run duration, distinguish a crash from a job that never started, and keep a history of every run.

Deadlines and grace periods

A heartbeat is only useful if something knows when the ping was due. Give the monitor your cron expression and it knows the schedule, so it can tell a late run from a dead job. When the ping does not arrive within the schedule plus a grace period you set, the check is marked down and you get alerted.

The grace period is how you avoid being paged for a job that just ran a few minutes long. Set it to cover a normal slow run, and let anything past that page you. Flap detection handles the job that succeeds, misses one window, then recovers, so a single blip does not wake you up.

Put cron checks next to your uptime checks

A cron job failing is the same kind of event as your API going down: something you rely on stopped working. With Cronaut the heartbeat check runs on the same engine as your HTTP and SSL checks, so a silent backup failure and a downed endpoint show up on the same dashboard and the same status page. One place to look when something feels off.

For the full picture, see cron job monitoring and how it sits next to uptime monitoring.

Try Cronaut free

Uptime, cron and a self-updating status page in one tool.

Start free