123 lines
4.0 KiB
Bash
123 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
||
# =============================================================================
|
||
# restore-postgres.sh – Wiederherstellung einer PostgreSQL-Datenbank aus Borg
|
||
# Läuft auf dem Raspberry Pi
|
||
# =============================================================================
|
||
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
CONFIG_FILE="${SCRIPT_DIR}/../config/backup.conf"
|
||
source "$CONFIG_FILE"
|
||
|
||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||
log() { echo -e "${BLUE}[RESTORE]${NC} $*"; }
|
||
log_ok() { echo -e "${GREEN}[RESTORE] ✓${NC} $*"; }
|
||
log_warn(){ echo -e "${YELLOW}[RESTORE] ⚠${NC} $*"; }
|
||
log_err() { echo -e "${RED}[RESTORE] ✗${NC} $*" >&2; }
|
||
|
||
export BORG_PASSPHRASE
|
||
export BORG_REPO
|
||
|
||
usage() {
|
||
echo ""
|
||
echo "Verwendung: $0 [OPTIONEN]"
|
||
echo ""
|
||
echo "Optionen:"
|
||
echo " -l, --list Verfügbare Archive auflisten"
|
||
echo " -a, --archive ARCHIVE Archiv-Name (z.B. mydb-2025-01-15T02:30)"
|
||
echo " -d, --database DB Ziel-Datenbank für Wiederherstellung"
|
||
echo " -t, --target-host HOST Ziel-Host (Standard: ${PG_HOST})"
|
||
echo " -o, --output-dir DIR Nur als Datei extrahieren (kein DB-Import)"
|
||
echo " -h, --help Diese Hilfe anzeigen"
|
||
echo ""
|
||
echo "Beispiele:"
|
||
echo " $0 --list"
|
||
echo " $0 --archive mydb-2025-01-15T02:30 --database mydb_restored"
|
||
echo " $0 --archive mydb-2025-01-15T02:30 --output-dir /tmp/restore"
|
||
echo ""
|
||
exit 0
|
||
}
|
||
|
||
list_archives() {
|
||
log "Verfügbare Archive in ${BORG_REPO}:"
|
||
echo ""
|
||
borg list --short "${BORG_REPO}" | sort -r | while read -r archive; do
|
||
local info
|
||
info=$(borg info "${BORG_REPO}::${archive}" 2>/dev/null | grep -E "Time|Duration|Deduplicated" || echo "")
|
||
echo " 📦 ${archive}"
|
||
echo "$info" | sed 's/^/ /'
|
||
echo ""
|
||
done
|
||
}
|
||
|
||
restore_to_db() {
|
||
local archive="$1"
|
||
local target_db="$2"
|
||
local target_host="${3:-$PG_HOST}"
|
||
|
||
log_warn "ACHTUNG: Datenbank '${target_db}' auf '${target_host}' wird überschrieben!"
|
||
read -rp "Fortfahren? (ja/NEIN): " confirm
|
||
[[ "$confirm" != "ja" ]] && { log "Abgebrochen."; exit 0; }
|
||
|
||
log "Stelle '${archive}' → '${target_db}' auf '${target_host}' wieder her..."
|
||
|
||
# Dump aus Borg extrahieren und direkt per SSH zu pg_restore pipen
|
||
borg extract --stdout "${BORG_REPO}::${archive}" \
|
||
| ssh -i "${SSH_KEY_PATH}" \
|
||
-o StrictHostKeyChecking=accept-new \
|
||
"${PG_SSH_USER}@${target_host}" \
|
||
"sudo -u ${PG_DB_USER} pg_restore \
|
||
--dbname=${target_db} \
|
||
--no-owner \
|
||
--no-privileges \
|
||
--clean \
|
||
--if-exists \
|
||
--format=custom"
|
||
|
||
log_ok "Wiederherstellung abgeschlossen!"
|
||
}
|
||
|
||
extract_to_dir() {
|
||
local archive="$1"
|
||
local output_dir="$2"
|
||
|
||
mkdir -p "$output_dir"
|
||
log "Extrahiere '${archive}' nach '${output_dir}'..."
|
||
borg extract --destination "$output_dir" "${BORG_REPO}::${archive}"
|
||
log_ok "Datei(en) in: ${output_dir}"
|
||
ls -lh "$output_dir"
|
||
}
|
||
|
||
# --- Argumente parsen --------------------------------------------------------
|
||
LIST=false
|
||
ARCHIVE=""
|
||
DATABASE=""
|
||
TARGET_HOST="${PG_HOST}"
|
||
OUTPUT_DIR=""
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
-l|--list) LIST=true ;;
|
||
-a|--archive) ARCHIVE="$2"; shift ;;
|
||
-d|--database) DATABASE="$2"; shift ;;
|
||
-t|--target-host) TARGET_HOST="$2"; shift ;;
|
||
-o|--output-dir) OUTPUT_DIR="$2"; shift ;;
|
||
-h|--help) usage ;;
|
||
*) log_err "Unbekannte Option: $1"; usage ;;
|
||
esac
|
||
shift
|
||
done
|
||
|
||
# --- Hauptlogik --------------------------------------------------------------
|
||
if $LIST; then
|
||
list_archives
|
||
elif [[ -n "$ARCHIVE" && -n "$OUTPUT_DIR" ]]; then
|
||
extract_to_dir "$ARCHIVE" "$OUTPUT_DIR"
|
||
elif [[ -n "$ARCHIVE" && -n "$DATABASE" ]]; then
|
||
restore_to_db "$ARCHIVE" "$DATABASE" "$TARGET_HOST"
|
||
else
|
||
log_err "Keine gültige Aktion angegeben."
|
||
usage
|
||
fi
|