148 lines
4.7 KiB
Bash
Executable file
148 lines
4.7 KiB
Bash
Executable file
#!/bin/bash
|
||
# Steuerkram – Restore-Script
|
||
# Spielt ein Backup-Paar (DB + Uploads) ein und führt anschließend alle
|
||
# ausstehenden Migrationen aus.
|
||
#
|
||
# Usage:
|
||
# ./scripts/restore.sh # neuestes vollständiges Backup
|
||
# ./scripts/restore.sh 20260517_134945 # bestimmten Timestamp
|
||
|
||
set -eo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
BACKUP_DIR="$PROJECT_DIR/backups"
|
||
COMPOSE="docker compose -f $PROJECT_DIR/docker-compose.yml --project-directory $PROJECT_DIR"
|
||
|
||
# --- Timestamp ermitteln ---
|
||
if [ -n "$1" ]; then
|
||
TS="$1"
|
||
else
|
||
# Neuesten Timestamp finden, für den BEIDE Dateien existieren
|
||
TS=""
|
||
for DB_FILE in $(ls -t "$BACKUP_DIR"/steuerkram_db_????????_??????.sql 2>/dev/null); do
|
||
CANDIDATE=$(basename "$DB_FILE" .sql | sed 's/steuerkram_db_//')
|
||
UPL_FILE="$BACKUP_DIR/steuerkram_uploads_${CANDIDATE}.tar.gz"
|
||
if [ -f "$UPL_FILE" ]; then
|
||
TS="$CANDIDATE"
|
||
break
|
||
fi
|
||
done
|
||
fi
|
||
|
||
DB_FILE="$BACKUP_DIR/steuerkram_db_${TS}.sql"
|
||
UPL_FILE="$BACKUP_DIR/steuerkram_uploads_${TS}.tar.gz"
|
||
|
||
# --- Dateien prüfen ---
|
||
if [ -z "$TS" ]; then
|
||
echo "FEHLER: Kein vollständiges Backup-Paar (DB + Uploads) gefunden." >&2
|
||
exit 1
|
||
fi
|
||
if [ ! -f "$DB_FILE" ]; then
|
||
echo "FEHLER: DB-Backup nicht gefunden: $DB_FILE" >&2
|
||
exit 1
|
||
fi
|
||
if [ ! -f "$UPL_FILE" ]; then
|
||
echo "FEHLER: Uploads-Backup nicht gefunden: $UPL_FILE" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "========================================"
|
||
echo " Steuerkram Restore – $TS"
|
||
echo "========================================"
|
||
echo " DB: $DB_FILE"
|
||
echo " Uploads: $UPL_FILE"
|
||
echo ""
|
||
|
||
# --- Sicherheitsabfrage ---
|
||
read -r -p "Vorhandene Datenbank und Uploads werden ÜBERSCHRIEBEN. Fortfahren? [j/N] " CONFIRM
|
||
if [[ ! "$CONFIRM" =~ ^[jJyY]$ ]]; then
|
||
echo "Abgebrochen."
|
||
exit 0
|
||
fi
|
||
|
||
# --- Container-Status prüfen ---
|
||
if ! $COMPOSE ps --status running db | grep -q "db"; then
|
||
echo "FEHLER: DB-Container läuft nicht. Bitte erst 'docker compose up -d' ausführen." >&2
|
||
exit 1
|
||
fi
|
||
if ! $COMPOSE ps --status running web | grep -q "web"; then
|
||
echo "FEHLER: Web-Container läuft nicht." >&2
|
||
exit 1
|
||
fi
|
||
|
||
# --- 1. Datenbank einspielen ---
|
||
echo ""
|
||
echo "[1/3] Datenbank importieren..."
|
||
$COMPOSE exec -T db mariadb -u root -prootpass steuerkram < "$DB_FILE"
|
||
echo " OK"
|
||
|
||
# --- 2. Nutzdateien einspielen ---
|
||
# Das Archiv wird zunächst ausgepackt und dann normalisiert. Unterstützt werden
|
||
# alle Ablagen, die im Lauf der Zeit im Einsatz waren:
|
||
# belege/, logo/ aktuelle Struktur
|
||
# legacy-uploads/ gemeinsame Ablage vor der Trennung
|
||
# uploads/ Web-Root-Ablage vor Fix #116
|
||
# In allen Fällen landet ein Unterordner logo/ in data/logo, alles Übrige in
|
||
# data/belege.
|
||
echo "[2/3] Belege und Logo entpacken..."
|
||
$COMPOSE exec -T web sh -c '
|
||
set -e
|
||
STAGE=/tmp/restore-stage
|
||
rm -rf "$STAGE" && mkdir -p "$STAGE"
|
||
cat > /tmp/restore.tar.gz
|
||
tar -xzf /tmp/restore.tar.gz -C "$STAGE"
|
||
rm -f /tmp/restore.tar.gz
|
||
|
||
BELEGE=/var/www/html/data/belege
|
||
LOGO=/var/www/html/data/logo
|
||
mkdir -p "$BELEGE" "$LOGO"
|
||
|
||
RESTORED_B=0
|
||
RESTORED_L=0
|
||
|
||
# Aktuelle Struktur
|
||
if [ -d "$STAGE/belege" ]; then
|
||
cp -a "$STAGE/belege/." "$BELEGE/" && RESTORED_B=1
|
||
fi
|
||
if [ -d "$STAGE/logo" ]; then
|
||
cp -a "$STAGE/logo/." "$LOGO/" && RESTORED_L=1
|
||
fi
|
||
|
||
# Ältere Sammelablagen auf die neue Struktur verteilen
|
||
for old in legacy-uploads uploads; do
|
||
[ -d "$STAGE/$old" ] || continue
|
||
echo " Älteres Archivformat \"$old/\" erkannt – wird verteilt."
|
||
if [ -d "$STAGE/$old/logo" ]; then
|
||
cp -a "$STAGE/$old/logo/." "$LOGO/" && RESTORED_L=1
|
||
rm -rf "$STAGE/$old/logo"
|
||
fi
|
||
if [ -n "$(ls -A "$STAGE/$old" 2>/dev/null)" ]; then
|
||
cp -a "$STAGE/$old/." "$BELEGE/" && RESTORED_B=1
|
||
fi
|
||
done
|
||
|
||
rm -rf "$STAGE"
|
||
chown -R www-data:www-data "$BELEGE" "$LOGO"
|
||
|
||
echo " Belege: $(find "$BELEGE" -type f | wc -l) Datei(en), Logo: $(find "$LOGO" -type f | wc -l) Datei(en)"
|
||
if [ "$RESTORED_B" = "0" ] && [ "$RESTORED_L" = "0" ]; then
|
||
echo " WARNUNG: Das Archiv enthielt keine bekannten Verzeichnisse!" >&2
|
||
fi
|
||
' < "$UPL_FILE"
|
||
echo " OK"
|
||
|
||
# --- 3. Migrationen ---
|
||
echo "[3/3] Migrationen prüfen und einspielen..."
|
||
MIGRATE_OUT=$($COMPOSE exec -T web php scripts/intern/migrate.php 2>&1)
|
||
echo "$MIGRATE_OUT" | sed 's/^/ /'
|
||
if echo "$MIGRATE_OUT" | grep -q "FEHLER"; then
|
||
echo ""
|
||
echo "WARNUNG: Mindestens eine Migration ist fehlgeschlagen!" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
echo "========================================"
|
||
echo " Restore abgeschlossen."
|
||
echo "========================================"
|