Files
2026-03-30 10:53:17 +02:00

103 lines
3.4 KiB
Bash

#!/bin/bash
# Backup FULL con atomicità, cleanup, log completi e sicurezza operativa
# Sicuro per cluster Galera
# Autore: Marco + Copilot
set -euo pipefail
# Aumenta i file descriptor disponibili
ulimit -n 65536
# Directory base dei backup
BACKUP_BASE=/var/backups/tscale01
# Timestamp per la directory del backup
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
# Directory finale del backup FULL
TARGET="$BACKUP_BASE/backup-full-$TIMESTAMP"
# File di log generale
LOGFILE=/var/log/mariadb-backup.log
# Lockfile per evitare esecuzioni concorrenti
LOCKFILE=/var/lock/mariadb-backup.lock
# Nome del server per i log
SERVER_NAME=$(hostname -s)
# Assicura che il logfile esista e abbia permessi sicuri
touch "$LOGFILE"
chown root:root "$LOGFILE"
chmod 600 "$LOGFILE"
(
# FLOCK: evita che due backup partano insieme
flock -n 9 || {
echo "[$(date '+%F %T')] [$SERVER_NAME] SKIP: another backup is running" >> "$LOGFILE"
exit 0
}
# Crea directory del backup
mkdir -p "$TARGET"
chown mysql:mysql "$TARGET"
chmod 750 "$TARGET"
# File temporaneo per catturare errori del backup
TMPLOG=$(mktemp /tmp/mariadb-backup-full.XXXXXX)
echo "---------------------" >> "$LOGFILE"
echo "[$(date '+%F %T')] [$SERVER_NAME] START backup FULL $TARGET" >> "$LOGFILE"
# Esecuzione backup FULL
if mariadb-backup \
--defaults-file=/etc/mysql/backup.conf \
--backup \
--target-dir="$TARGET" \
--verbose >"$TMPLOG" 2>&1; then
echo "[$(date '+%F %T')] [$SERVER_NAME] NOTE: FULL created UNPREPARED at $TARGET" >> "$LOGFILE"
echo "[$(date '+%F %T')] [$SERVER_NAME] END backup FULL $TARGET" >> "$LOGFILE"
# Misura dimensione apparente (byte logici)
size_apparent_bytes=$(find "$TARGET" -type f -printf '%s\n' 2>/dev/null | awk '{s+=$1} END{print s+0}')
size_apparent_human=$(numfmt --to=iec --suffix=B "$size_apparent_bytes" 2>/dev/null || echo "${size_apparent_bytes}B")
# Misura spazio su disco effettivo (byte allocati)
size_disk_bytes=$(du -s --block-size=1 "$TARGET" 2>/dev/null | cut -f1 || echo 0)
size_disk_human=$(numfmt --to=iec --suffix=B "$size_disk_bytes" 2>/dev/null || echo "${size_disk_bytes}B")
echo "[$(date '+%F %T')] [$SERVER_NAME] SIZE apparent: $size_apparent_human ($size_apparent_bytes bytes)" >> "$LOGFILE"
echo "[$(date '+%F %T')] [$SERVER_NAME] SIZE on-disk: $size_disk_human ($size_disk_bytes bytes)" >> "$LOGFILE"
echo "[$(date '+%F %T')] [$SERVER_NAME] RESULT: OK, no errors" >> "$LOGFILE"
rm -f "$TMPLOG"
else
# Backup fallito → log + cleanup directory
echo "[$(date '+%F %T')] [$SERVER_NAME] ERROR during FULL backup for $TARGET. See $TMPLOG" >> "$LOGFILE"
tail -n 200 "$TMPLOG" >> "$LOGFILE"
echo "[$(date '+%F %T')] [$SERVER_NAME] CLEANUP: removing incomplete FULL backup directory $TARGET" >> "$LOGFILE"
rm -rf "$TARGET"
rm -f "$TMPLOG"
exit 1
fi
# Rotazione: mantieni 7 giorni di FULL
TO_DELETE=$(find "$BACKUP_BASE" -maxdepth 1 -type d -name 'backup-full-*' -mtime +7 -print 2>/dev/null || true)
if [ -n "$TO_DELETE" ]; then
echo "[$(date '+%F %T')] [$SERVER_NAME] ROTATE: removing old FULL backups:" >> "$LOGFILE"
echo "$TO_DELETE" >> "$LOGFILE"
echo "$TO_DELETE" | tr '\n' '\0' | xargs -0 -r rm -rf --
else
echo "[$(date '+%F %T')] [$SERVER_NAME] ROTATE: no FULL backups to remove (<=7 days)" >> "$LOGFILE"
fi
echo " " >> "$LOGFILE"
) 9>"$LOCKFILE"