How to monitor cron jobs

To monitor a cron job, have it make an HTTP request to a monitoring URL each time it runs, and let the monitor alert you when that request doesn't arrive on schedule. With Cronomonitor that's one curl command added to the job's line in your crontab.

Why monitor it

Cron itself never tells you when something goes wrong. A job that's been deleted, a server that rebooted and lost its crontab, a full disk or a script that exits with an error all look the same from the outside: nothing happens. Usually nobody notices until the backup is needed.

1. Create a check

Sign up for Cronomonitor, create a project and add a check named after the job. Give it the job's schedule, here the cron expression 0 3 * * * (every day at 3am, UTC), and a grace period that covers how long the job normally takes.

The check gives you a unique ping URL. Every snippet below is also on the check's page in the dashboard, already filled in with that URL and schedule.

2. Add the ping to your job

Example
# Reports the job's exit code, so a failure alerts straight away
0 3 * * * /path/to/your-job.sh; curl -fsS -m 10 --retry 3 -o /dev/null https://cronomonitor.com/api/ping/<your-check-id>/$?

# Or also time each run and keep its output in the ping log
0 3 * * * curl -fsS -m 10 --retry 3 -o /dev/null https://cronomonitor.com/api/ping/<your-check-id>/start; OUT=$(/path/to/your-job.sh 2>&1); curl -fsS -m 10 --retry 3 -o /dev/null --data-binary "$OUT" https://cronomonitor.com/api/ping/<your-check-id>/$?

How it works

The first line runs the job, then pings the check with the job's exit code: $? holds the exit code of the last command, so 0 reports a success and anything else a failure, which alerts you straight away instead of waiting for the next missed run.

The second form also pings /start before the job, so Cronomonitor times each run and can alert you if one hangs, and sends the job's output with the final ping so you can read it in the check's ping log.

The curl options matter: -fsS stays quiet unless something goes wrong, -m 10 gives up after 10 seconds so a network problem can't hold the job up, and --retry 3 retries brief failures.

Import a whole crontab at once

If you have more than a few jobs, paste the output of crontab -l into a Cronomonitor project. It creates a check for every job with the same schedule, and gives you the crontab back with the ping already added to each line, ready to install with crontab -e.

Watch out for % and PATH

Cron treats an unescaped % in a command as a newline, so a date format such as $(date +%F) needs writing as $(date +\%F). Cron also runs jobs with a minimal PATH, so use full paths to scripts and programs, or set PATH at the top of the crontab.

Time zones

Cron uses the server's time zone. If your server runs in UTC but you think of the job as running at 3am London time, give the check a cron schedule in Europe/London, so Cronomonitor expects the job at the right moment through daylight-saving changes.

3. Test it

Run the job once by hand, or use Send a test ping on the check. The check turns green as soon as the first ping arrives, and from then on Cronomonitor expects the next one on schedule.

To check where alerts go, use Send test alert on the check. To see a real failure alert, make the job exit with an error once.

If the check says the job didn't run

Check the job is installed for the user you expect with crontab -l (or sudo crontab -l for root).

Look for cron's own log lines: grep CRON /var/log/syslog on Debian and Ubuntu, or journalctl -u cron (cronie: journalctl -u crond).

Run the exact line from the crontab by hand in a minimal environment, e.g. env -i /bin/sh -c '<command>', to catch PATH problems.

Try it on your own jobs

14-day free trial with every feature. No card required.

Start your free trial