Уведомления о результатах бэкапа
«Бэкап, который никто не проверяет, — это не бэкап». Простейший способ проверить — каждый раз получать короткое сообщение об успехе и громкое — об ошибке. Если ежедневной «зелёной» нотификации нет, что-то сломалось.
Универсальная обёртка
Заголовок раздела «Универсальная обёртка»Подойдёт для restic, borg, pg_dump, rsync, tar — чего угодно.
Сохраните как /usr/local/bin/notifly-wrap:
#!/usr/bin/env bash# Использование:# notifly-wrap "Имя задачи" -- команда для выполненияset -euset -a; source /etc/notifly.env; set +a
NAME="${1:?name required}"; shift[ "${1:-}" = "--" ] && shift
START=$(date +%s)HOST=$(hostname -s)LOG=$(mktemp)
if "$@" >"$LOG" 2>&1; then DUR=$(( $(date +%s) - START )) SIZE=$(wc -l <"$LOG") /usr/local/bin/notifly-send \ "✅ $NAME — OK ($HOST)" \ "Длительность: ${DUR}sСтрок лога: $SIZEХост: $HOST" 3 RC=0else RC=$? DUR=$(( $(date +%s) - START )) TAIL=$(tail -c 1500 "$LOG") /usr/local/bin/notifly-send \ "❌ $NAME — FAIL (rc=$RC) — $HOST" \ "Длительность: ${DUR}sКод: $RC
Последний вывод:$TAIL" 9fi
rm -f "$LOG"exit "$RC"sudo chmod +x /usr/local/bin/notifly-wrapПример: ежедневный бэкап PostgreSQL
Заголовок раздела «Пример: ежедневный бэкап PostgreSQL»/etc/cron.d/notifly-pg-backup:
SHELL=/bin/bash0 3 * * * postgres /usr/local/bin/notifly-wrap "pg_dump app" -- \ bash -c 'pg_dump -Fc app | gzip > /var/backups/pg/app-$(date +\%F).sql.gz'Каждое утро в 03:00 вы получите либо «✅ pg_dump app — OK», либо «❌ pg_dump app — FAIL» с хвостом stderr.
Пример: restic в S3
Заголовок раздела «Пример: restic в S3»0 4 * * * root /usr/local/bin/notifly-wrap "restic backup /etc /home /srv" -- \ /usr/local/bin/restic -r s3:s3.example.com/bucket backup /etc /home /srvПример: rsync на удалённый сервер
Заголовок раздела «Пример: rsync на удалённый сервер»30 2 * * * root /usr/local/bin/notifly-wrap "rsync /var/www → backup-host" -- \ rsync -aHAX --delete /var/www/ backup@backup-host:/data/www/«Канарейка»: сообщение, если бэкап вообще не запускался
Заголовок раздела ««Канарейка»: сообщение, если бэкап вообще не запускался»Если бэкап-скрипт сам упал и нотификация не отправилась, вы об этом не узнаете. Решение — отдельный «канарейка-таймер», который раз в день проверяет, есть ли свежий файл бэкапа:
/usr/local/bin/notifly-backup-canary:
#!/usr/bin/env bashset -euset -a; source /etc/notifly.env; set +a
DIR=/var/backups/pgLATEST=$(ls -t "$DIR"/*.sql.gz 2>/dev/null | head -1 || true)NOW=$(date +%s)
if [ -z "$LATEST" ]; then /usr/local/bin/notifly-send \ "🚨 Нет ни одного бэкапа в $DIR" \ "Канарейка не нашла файлов бэкапа на $(hostname -s)." 10 exit 1fi
AGE=$(( NOW - $(stat -c %Y "$LATEST") ))if [ "$AGE" -gt 90000 ]; then # > 25 часов /usr/local/bin/notifly-send \ "🚨 Старый бэкап на $(hostname -s)" \ "Последний файл: $(basename "$LATEST")Возраст: $((AGE/3600))ч." 10fiЗапускайте через cron в 11:00 — после ночного окна:
0 11 * * * root /usr/local/bin/notifly-backup-canary- Каждый день видна «жизнь» бэкапа. Зелёная нотификация = вы знаете, что система жива.
- При ошибке сразу видно причину — последние 1500 байт stderr идут в тело сообщения.
- Канарейка ловит «тихие» сбои: даже если основной скрипт не запустился, отдельный таймер всё равно прокричит.
Что улучшить дальше
Заголовок раздела «Что улучшить дальше»- Хранить размер бэкапа в сообщении и предупреждать, если он внезапно стал меньше или больше обычного на >50 %.
- Заворачивать туда же
pg_verifybackupилиrestic check— чтобы «зелёным» считался только проверенный бэкап.