Wrapper для cron
#!/usr/bin/env bash
set -euo pipefail
export NERVE_DSN="nerve://TOKEN:[email protected]"
if ! /opt/jobs/backup.sh; then
echo "backup cron failed on $(hostname)" | nerve send --severity alert
exit 1
fi
Crontab
15 3 * * * /opt/jobs/backup-with-nerve.sh
Не кладите root token, SSH key или database password в текст уведомления. Лучше отправлять короткий статус, hostname и ссылку на внутренний runbook.
Ловить stdout/stderr
Для cron важно сохранить последние строки ошибки. Иначе push скажет только “упало”, а причину все равно придется искать вручную.
#!/usr/bin/env bash
set -euo pipefail
export NERVE_DSN="nerve://TOKEN:[email protected]"
LOG="/tmp/backup-cron.log"
if ! /opt/jobs/backup.sh >"$LOG" 2>&1; then
{
echo "backup cron failed on $(hostname)"
tail -20 "$LOG"
} | nerve send --severity critical
exit 1
fi
Защита от спама
Если cron запускается каждые 5 минут, одна поломка может прислать сотню push. Добавьте простой cooldown-файл.
LOCK="/tmp/nerve-backup-alert.lock"
COOLDOWN=3600
if [ ! -f "$LOCK" ] || [ $(( $(date +%s) - $(stat -c %Y "$LOCK") )) -gt "$COOLDOWN" ]; then
echo "backup cron still failing on $(hostname)" | nerve send --severity critical
touch "$LOCK"
fi
Проверка что cron вообще жив
Отдельно полезен “dead man's switch”: успешный job обновляет timestamp-файл, а утренний check смотрит, что файл свежий. Это ловит случаи, когда cron не стартовал вообще.
# В конце успешного backup.sh
date +%s > /var/lib/myapp/backup.last_ok
# Отдельная утренняя проверка
LAST=$(cat /var/lib/myapp/backup.last_ok 2>/dev/null || echo 0)
AGE=$(( ($(date +%s) - LAST) / 3600 ))
[ "$AGE" -gt 26 ] && echo "backup cron stale: ${AGE}h" | nerve send --severity critical
PATH в cron
Если вручную nerve send работает, а из cron нет, почти всегда проблема в PATH. Укажите полный путь к бинарнику или задайте PATH в crontab.