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-цепочку.