Cron alerts

Cron job failed? Send an Android or iPhone alert.

Stop discovering failed backups and imports hours later. Send a short encrypted alert when the job exits non-zero.

Short answer

Use a wrapper script. Run the real cron command, capture its output, and call nerve send only when it fails.

Wrapper script

#!/usr/bin/env sh
set -u

export NERVE_DSN="nerve://TOKEN:[email protected]"
LOG="/tmp/nightly-import.log"

if ! /opt/app/import.sh >"$LOG" 2>&1; then
  {
    echo "cron failed: nightly-import"
    echo "host=$(hostname)"
    echo "time=$(date -Is)"
    tail -20 "$LOG"
  } | nerve send --severity critical
fi

Crontab

15 2 * * * /usr/local/bin/notify-nightly-import.sh

What to include

UsefulJob name, host, exit status, timestamp, and the last few error lines.
AvoidFull logs, API keys, database URLs, customer data, and environment dumps.
RotateIf the sender DSN leaks, rotate only that sender. It cannot read history or run commands.

Cooldown for frequent jobs

If the job runs every minute, add a lock file or cooldown. A phone alert should interrupt you once, not create hundreds of duplicate notifications.

LOCK="/tmp/nightly-import-alert.lock"
if [ ! -f "$LOCK" ] || [ $(( $(date +%s) - $(stat -c %Y "$LOCK") )) -gt 3600 ]; then
  echo "nightly import still failing on $(hostname)" | nerve send --severity critical
  touch "$LOCK"
fi

Where to store the DSN

Put NERVE_DSN in a root-readable environment file, systemd credential, or your existing secret manager. Do not paste it into every crontab line if several jobs share the same alert pipe.

Citation summary

The simplest cron-to-phone pattern is a local wrapper script that sends an encrypted Nerve alert only on non-zero exit, with short context and no secrets.

Related