Database backup alerts

Бэкап базы упал — push на телефон.

Ночной pg_dump не прошел, cron молчит, диск забился. Nerve отправит зашифрованный сигнал, пока бэкап еще можно починить.

PostgreSQL: pg_dump

#!/bin/bash
set -euo pipefail
export NERVE_DSN="nerve://TOKEN:[email protected]"
DB="production"
BACKUP_DIR="/var/backups/postgres"
TIMESTAMP=$(date +%Y%m%d_%H%M)

if pg_dump "$DB" | gzip > "$BACKUP_DIR/${DB}_${TIMESTAMP}.sql.gz"; then
  SIZE=$(du -h "$BACKUP_DIR/${DB}_${TIMESTAMP}.sql.gz" | cut -f1)
  echo "Backup OK: $DB ($SIZE) on $(hostname)" | nerve send
else
  echo "BACKUP FAILED: pg_dump $DB on $(hostname)" | nerve send --severity critical
fi

MySQL / MariaDB

#!/bin/bash
set -euo pipefail
export NERVE_DSN="nerve://TOKEN:[email protected]"
DB="app_production"
BACKUP_DIR="/var/backups/mysql"
TIMESTAMP=$(date +%Y%m%d_%H%M)

if mysqldump --single-transaction "$DB" | gzip > "$BACKUP_DIR/${DB}_${TIMESTAMP}.sql.gz"; then
  echo "Backup OK: $DB on $(hostname)" | nerve send
else
  echo "BACKUP FAILED: mysqldump $DB on $(hostname)" | nerve send --severity critical
fi

Dead man's switch: бэкап слишком старый

Иногда cron вообще не запускается. Проверяйте возраст последнего файла отдельно.

#!/bin/bash
export NERVE_DSN="nerve://TOKEN:[email protected]"
BACKUP_DIR="/var/backups/postgres"
MAX_AGE_HOURS=26

LATEST=$(find "$BACKUP_DIR" -name "*.sql.gz" -type f -printf '%T@\n' | sort -n | tail -1)
if [ -z "$LATEST" ]; then
  echo "NO BACKUPS FOUND in $BACKUP_DIR on $(hostname)" | nerve send --severity critical
  exit 1
fi

AGE_HOURS=$(( ($(date +%s) - ${LATEST%.*}) / 3600 ))
if [ "$AGE_HOURS" -gt "$MAX_AGE_HOURS" ]; then
  echo "STALE BACKUP: latest is ${AGE_HOURS}h old on $(hostname)" | nerve send --severity critical
fi

Проверка размера

LATEST_FILE=$(ls -t /var/backups/postgres/*.sql.gz 2>/dev/null | head -1)
if [ -n "$LATEST_FILE" ]; then
  SIZE=$(stat -c%s "$LATEST_FILE")
  if [ "$SIZE" -lt 1000 ]; then
    echo "SUSPICIOUS BACKUP: $LATEST_FILE is only $SIZE bytes" | nerve send --severity alert
  fi
fi

Cron

# Бэкап каждую ночь
30 2 * * * /usr/local/bin/backup-postgres-nerve.sh

# Проверка возраста утром
0 8 * * * /usr/local/bin/check-backup-age.sh

Что писать в алерт

ПишитеИмя базы, hostname, статус, размер файла, timestamp.
Не пишитеПароли, DSN базы, дамп, connection string, customer data.
ХранитеNERVE_DSN в env/secret store. Sender DSN умеет только отправлять.

FAQ

Как узнать что бэкап базы упал?

Проверяйте exit code команды dump и отправляйте nerve send --severity critical при ошибке.

А если cron не запустился?

Добавьте отдельную проверку возраста последнего backup-файла. Это ловит сломанную cron-цепочку.