Recipe · cron / systemd
Get notified when a cron job or systemd service fails
Wrap a scheduled job so failure — and only failure — reaches your phone, without cron's noisy default of emailing every run.
Cron’s default is to email every run’s output to a local mail spool nobody reads. The fix is the same either way: check the exit code, and only notify on failure.
Cron
Wrap the job in a small script rather than editing the crontab line itself — easier to test and to reuse:
#!/usr/bin/env bash
set -euo pipefail
if ! /usr/local/bin/nightly-backup.sh; then
curl -sS -X POST "https://<host>/events/<username>/Backups" \
-H "Content-Type: application/json" \
-d '{
"title": "Nightly backup failed",
"message": "'"$(hostname)"' — see /var/log/backup.log",
"priority": "High",
"nature": "error"
}'
exit 1
fi
Point cron at the wrapper, not the underlying command:
0 3 * * * /usr/local/bin/backup-with-alert.sh
systemd
A oneshot service can use OnFailure= to trigger a second unit only when the first one fails — no wrapper script needed:
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
OnFailure=notify-paperplane@%n.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/nightly-backup.sh
# /etc/systemd/system/notify-paperplane@.service
[Unit]
Description=Notify Paperplane that %i failed
[Service]
Type=oneshot
ExecStart=/usr/bin/curl -sS -X POST "https://<host>/events/<username>/Backups" \
-H "Content-Type: application/json" \
-d '{"title":"systemd unit failed","message":"%i","priority":"High","nature":"error"}'
%i and %n expand to the failed unit’s name, so one notify-paperplane@ template covers every service you attach it to.