#!/usr/bin/env bash # Sichert Datenbank, .env und Uploads des Planers. # Wiederherstellung: siehe README.md, Abschnitt "Sicherung und Wiederherstellung". set -euo pipefail WURZEL="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$WURZEL" ZIEL="${WURZEL}/sicherungen" AUFBEWAHRUNG_TAGE=30 NUR_DATENBANK=0 hilfe() { cat <<'ENDE' Verwendung: backup.sh [Optionen] --ziel Ablageort der Sicherung (Standard: ./sicherungen) --tage Aufbewahrung in Tagen (Standard: 30, 0 = unbegrenzt) --nur-datenbank Nur den Datenbank-Dump erzeugen --hilfe Diese Übersicht Erzeugt je Lauf zwei Dateien: planer-db-.dump Datenbank im Custom-Format von pg_dump planer-dateien-.tar.gz .env und der Ordner uploads ENDE } meldung() { printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1"; } fehler() { printf '%s Fehler: %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1" >&2 exit 1 } while [ $# -gt 0 ]; do case "$1" in --ziel) ZIEL="${2:-}" [ -n "$ZIEL" ] || fehler '--ziel braucht einen Pfad.' shift 2 ;; --tage) AUFBEWAHRUNG_TAGE="${2:-}" case "$AUFBEWAHRUNG_TAGE" in ''|*[!0-9]*) fehler '--tage braucht eine ganze Zahl.' ;; esac shift 2 ;; --nur-datenbank) NUR_DATENBANK=1 shift ;; --hilfe|-h) hilfe exit 0 ;; *) fehler "Unbekannte Option '$1'. 'backup.sh --hilfe' zeigt die Übersicht." ;; esac done command -v docker >/dev/null 2>&1 || fehler 'docker fehlt.' [ -f "$WURZEL/.env" ] || fehler '.env fehlt – im Projektverzeichnis aufrufen.' # Nur die benötigten Werte lesen, nicht die ganze Datei ausführen. lies_env() { local schluessel="$1" standard="${2:-}" local wert wert="$(grep -E "^${schluessel}=" "$WURZEL/.env" | tail -1 | cut -d= -f2- || true)" wert="${wert%\"}" wert="${wert#\"}" printf '%s' "${wert:-$standard}" } PG_BENUTZER="$(lies_env POSTGRES_USER planer)" PG_DATENBANK="$(lies_env POSTGRES_DB planer)" DB_CONTAINER="$(docker compose ps -q db)" [ -n "$DB_CONTAINER" ] || fehler 'Der Datenbank-Container läuft nicht. Erst "docker compose up -d db".' ZEITSTEMPEL="$(date '+%Y-%m-%d_%H-%M-%S')" mkdir -p "$ZIEL" DUMP="$ZIEL/planer-db-${ZEITSTEMPEL}.dump" meldung "Datenbank sichern nach $DUMP" # -Fc ist das Custom-Format: komprimiert und mit pg_restore selektiv einspielbar. docker exec "$DB_CONTAINER" pg_dump -U "$PG_BENUTZER" -d "$PG_DATENBANK" -Fc > "$DUMP" if [ ! -s "$DUMP" ]; then rm -f "$DUMP" fehler 'Der Dump ist leer geblieben.' fi meldung "Datenbank gesichert ($(du -h "$DUMP" | cut -f1))." if [ "$NUR_DATENBANK" -eq 0 ]; then DATEIEN="$ZIEL/planer-dateien-${ZEITSTEMPEL}.tar.gz" meldung "Dateien sichern nach $DATEIEN" ZU_SICHERN=(.env) [ -d "$WURZEL/uploads" ] && ZU_SICHERN+=(uploads) tar -czf "$DATEIEN" -C "$WURZEL" "${ZU_SICHERN[@]}" meldung "Dateien gesichert ($(du -h "$DATEIEN" | cut -f1))." fi if [ "$AUFBEWAHRUNG_TAGE" -gt 0 ]; then meldung "Sicherungen älter als $AUFBEWAHRUNG_TAGE Tage entfernen." find "$ZIEL" -maxdepth 1 -type f -name 'planer-*' -mtime "+$AUFBEWAHRUNG_TAGE" -print -delete fi meldung 'Sicherung abgeschlossen.'