Monitor a crontab job
Cron doesn’t tell anyone when a job fails. The script errors, the server reboots, or someone edits the crontab, and the job quietly stops. A heartbeat check notices: the job reports to Pingstack after it succeeds, and Pingstack alerts you when that report doesn’t arrive on time.
By the end of this recipe you’ll have a heartbeat check that expects the job’s schedule, a private file holding its ping URL, and a wrapper script that reports each successful run.
1. Create a heartbeat check that matches the schedule
Section titled “1. Create a heartbeat check that matches the schedule”Find the job’s line in crontab -l:
0 3 * * * /opt/jobs/backup.shCreate a heartbeat check and set its
schedule to Cron with the same expression (0 3 * * *). Cron runs jobs in
the server’s local timezone unless your cron supports and sets CRON_TZ, so
choose the server’s timezone in Pingstack. Run date on the server if you’re
not sure. See schedules and timezones.
Set a grace period longer than the job’s usual runtime, plus a margin. Attach a notification group.
2. Keep the ping URL in a private file
Section titled “2. Keep the ping URL in a private file”Copy the location’s ping URL from the check in Pingstack. Anyone who has it can report a run, so keep it out of the crontab, scripts in version control and shell history. Save it in a file only the job’s user can read:
install -m 600 /dev/null ~/.pingstack-backupread -rs URL && printf 'PINGSTACK_PING_URL=%s\n' "$URL" > ~/.pingstack-backupread -rs waits for you to paste the URL without echoing it, then press
Enter.
3. Report success from a wrapper script
Section titled “3. Report success from a wrapper script”Run the job through a small wrapper that pings only when the job succeeds:
#!/usr/bin/env bashset -euo pipefailsource ~/.pingstack-backup
/opt/jobs/backup.sh
curl --fail --silent --show-error --max-time 10 --retry 3 \ "$PINGSTACK_PING_URL" > /dev/nullset -euo pipefail stops the script at the first failing command, including
a failure early in a pipeline, so a failed job sends nothing. --retry 3
covers a brief network blip.
Make it executable and point the crontab at it:
chmod 700 /opt/jobs/backup-monitored.sh0 3 * * * /opt/jobs/backup-monitored.shIf the job can run longer than its schedule, stop runs from overlapping with
flock:
0 3 * * * flock -n /tmp/backup.lock /opt/jobs/backup-monitored.shOr use the pingstack command
Section titled “Or use the pingstack command”The pingstack command replaces the wrapper
script, and also reports failures right away with the end of the job’s
output, plus each run’s time:
0 2 * * * set -a; . "$HOME/.pingstack-backup"; /usr/local/bin/pingstack run -- /opt/jobs/backup.sh4. Confirm the first report
Section titled “4. Confirm the first report”Run the wrapper by hand as the cron user:
/opt/jobs/backup-monitored.shOpen the check in Pingstack and confirm the location received a heartbeat and
shows a next deadline. A run that works by hand but not from cron usually
means cron’s environment is different: a shorter PATH, no shell profile, or
a different working directory. Use absolute paths in the wrapper.
Optional: report a number
Section titled “Optional: report a number”Send a count the job produces as a numeric value, then set warning and critical thresholds on the check. A backup that succeeds but is far too small can then still raise an alert.
SIZE_MB=$(du -sm /backups/latest | cut -f1)curl --fail --silent --show-error --max-time 10 --retry 3 \ --get --data-urlencode "value=$SIZE_MB" "$PINGSTACK_PING_URL" > /dev/nullWhy a healthy job might still alert
Section titled “Why a healthy job might still alert”- Timezone mismatch. The check expects 03:00 in its timezone; cron ran at 03:00 in the server’s. Make them the same, or use UTC on both.
- Daylight saving. Local-time schedules shift twice a year. UTC avoids it.
- Slow runs. A backup that grows over time eventually outlasts the grace period. Lengthen it.
- Server asleep or down. Cron doesn’t catch up on runs missed while the machine was off. That’s an alert worth getting.
If alerts still don’t match what you expect, see troubleshooting monitoring.