Finanzmanager/scripts/backup.sh
fds2610-bot b1712bb7ea Phase 0: Projektgerüst mit nginx, php-fpm und MariaDB
Docker Compose mit drei Services (nginx auf Port 8000), Migrationsmechanik,
Update- und Backup-Skript. Anwendung: Router mit CSRF-Prüfung, Anmeldung und
Ersteinrichtung, zentraler Einstellungsdialog mit Reitern, ein- und
ausschaltbares Debug-Log mit Maskierung von Zugangsdaten.

Layout nach Vorbild des FinanzManagers: feste Navigation links,
Werkzeugleiste oben, Tab-Leiste; Farbschema hell/dunkel/System.

Tests: 51 PHP-Prüfungen und 7 Playwright-Tests, alle grün.
2026-08-09 20:21:42 +02:00

77 lines
2.2 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
#
# Sichert Datenbank und Nutzdaten nach backups/.
#
# Rotation: 7 Tages-, 4 Wochen-, 12 Monats-Backups. Ein flock verhindert, dass
# sich zwei Läufe überholen.
#
# ./scripts/backup.sh
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/.."
ZIEL="backups"
mkdir -p "$ZIEL"
exec 9>"$ZIEL/.lock"
if ! flock -n 9; then
echo "Ein Backup läuft bereits." >&2
exit 0
fi
STEMPEL="$(date +%Y%m%d_%H%M%S)"
DB_PASS="${DB_PASS:-finanzmanager}"
echo "Sichere Datenbank …"
docker compose exec -T db mariadb-dump \
-u finanzmanager -p"$DB_PASS" \
--single-transaction --routines --events \
finanzmanager > "$ZIEL/db_${STEMPEL}.sql"
echo "Sichere Nutzdaten …"
# data/mariadb bleibt außen vor – die Datenbank steckt bereits im Dump.
tar czf "$ZIEL/daten_${STEMPEL}.tar.gz" \
--exclude='data/mariadb' \
data 2>/dev/null || true
# ── Rotation ────────────────────────────────────────────────────────────────
# Behalten: die letzten 7 Tage vollständig, danach je ein Backup pro Woche
# (4 Wochen) und pro Monat (12 Monate).
python3 - "$ZIEL" <<'PY'
import os, re, sys, time
from datetime import datetime
ziel = sys.argv[1]
muster = re.compile(r'^(db|daten)_(\d{8})_(\d{6})\.(sql|tar\.gz)$')
dateien = []
for name in os.listdir(ziel):
treffer = muster.match(name)
if treffer:
stempel = datetime.strptime(treffer.group(2) + treffer.group(3), '%Y%m%d%H%M%S')
dateien.append((stempel, name))
dateien.sort(reverse=True)
jetzt = datetime.now()
behalten, wochen, monate = set(), set(), set()
for stempel, name in dateien:
alter = (jetzt - stempel).days
if alter <= 7:
behalten.add(name)
continue
woche = stempel.isocalendar()[:2]
monat = (stempel.year, stempel.month)
if alter <= 35 and woche not in wochen:
wochen.add(woche); behalten.add(name)
elif alter <= 400 and monat not in monate:
monate.add(monat); behalten.add(name)
for _, name in dateien:
if name not in behalten:
os.remove(os.path.join(ziel, name))
print(f"Entfernt: {name}")
PY
echo "Backup abgeschlossen: $ZIEL/db_${STEMPEL}.sql"