#!/bin/bash # Denni obnova zrcadla Medicus DB z nejnovejsi gbak zalohy do Firebird kontejneru # + GFS retence zaloh. # # Zalohy se v adresari HROMADI a nejnovejsi se muze prave PRENASET pres rsync. Proto: # - vybira nejnovejsi MEDICUS_*.zip podle nazvu (RRMMDD_HHMM -> lexikalne = chronologicky) # - pamatuje si posledni uspesne restorovanou (last_restored.txt) -> neni-li nic novejsiho, konci # - ceka, az velikost prestane rust (probiha-li rsync), a overi integritu (unzip -t), # teprve pak restoruje -> nikdy nezpracuje nekompletni prenos # - marker se zapise az PO uspesnem restoru # - na konci spusti GFS retenci zaloh (prune_backups.sh) set -euo pipefail NAME=firebird-medicus APPDATA=/mnt/user/appdata/firebird-medicus DATA="$APPDATA/fb/data" WORK="$APPDATA/work" BACKUP_DIR=/mnt/user/OrdinaceSynology/MedicusBackup GBAK=/usr/local/firebird/bin/gbak PASS=masterkey BASE_DIR=/mnt/user/Scripts/MedicusFirebird STATE="$BASE_DIR/last_restored.txt" LOG="$BASE_DIR/restore.log" # Retence: ostra (maze dle GFS 30d/8t/12m). Pro testovaci beh prepnout na 1 (jen vypis). RETENTION_DRYRUN="${RETENTION_DRYRUN:-0}" exec >>"$LOG" 2>&1 exec 9>"$BASE_DIR/.restore.lock" flock -n 9 || { echo "$(date '+%F %T') jiny restore uz bezi -> koncim."; exit 0; } echo "===== $(date '+%F %T') restore start =====" mkdir -p "$WORK" "$DATA" # --- 1) nejnovejsi zaloha podle nazvu --- ZIP=$(ls -1 "$BACKUP_DIR"/MEDICUS_*.zip 2>/dev/null | sort | tail -1 || true) if [ -z "${ZIP:-}" ]; then echo "CHYBA: zadna zaloha v $BACKUP_DIR"; exit 1; fi ZIP_BASE=$(basename "$ZIP") LAST=$(cat "$STATE" 2>/dev/null || echo "") echo "Nejnovejsi: $ZIP_BASE | posledni restorovana: ${LAST:-}" # --- 2) uz restorovana? --- if [ "$ZIP_BASE" = "$LAST" ]; then echo "Nic noveho -> restore preskocen." else # --- 3) pockej na dokonceni prenosu (velikost se ustali) --- prev=-1; stable=0 for i in $(seq 1 80); do # max ~20 min cekani na rsync cur=$(stat -c %s "$ZIP" 2>/dev/null || echo 0) if [ "$cur" = "$prev" ] && [ "$cur" -gt 0 ]; then stable=1; break; fi echo " ...$ZIP_BASE = $cur B, cekam na ustaleni" prev=$cur; sleep 15 done [ "$stable" = "1" ] || { echo "CHYBA: $ZIP_BASE se stale meni -> koncim (priste)."; exit 1; } # --- 4) integrita (nekompletni/poskozeny zip neprojde) --- echo "unzip -t ..." unzip -tqq "$ZIP" || { echo "CHYBA: $ZIP_BASE neprosel unzip -t -> koncim."; exit 1; } # --- 5) rozbaleni .fbk --- rm -f "$WORK"/*.fbk unzip -o "$ZIP" -d "$WORK" >/dev/null FBK=$(ls -1t "$WORK"/*.fbk | head -1) FBK_BASE=$(basename "$FBK") echo "FBK: $FBK_BASE ($(du -h "$FBK" | cut -f1))" # --- 6) restore pres bezici server do noveho souboru --- docker start "$NAME" >/dev/null 2>&1 || true sleep 8 echo "gbak restore -> medicus_new.fdb ..." docker exec "$NAME" rm -f /firebird/data/medicus_new.fdb docker exec "$NAME" "$GBAK" -r -p 8192 -user SYSDBA -password "$PASS" \ "/work/$FBK_BASE" "localhost:/firebird/data/medicus_new.fdb" # --- 7) atomicky swap + restart --- echo "swap + restart ..." docker stop "$NAME" >/dev/null mv -f "$DATA/medicus_new.fdb" "$DATA/medicus.fdb" docker start "$NAME" >/dev/null sleep 8 rm -f "$WORK"/*.fbk # --- 8) marker az po uspechu --- echo "$ZIP_BASE" > "$STATE" echo "restore OK: $ZIP_BASE" fi # --- 9) GFS retence zaloh --- echo "--- retence zaloh (DRY_RUN=$RETENTION_DRYRUN) ---" DRY_RUN="$RETENTION_DRYRUN" "$BASE_DIR/prune_backups.sh" || echo "VAROVANI: prune_backups.sh selhal" echo "===== $(date '+%F %T') hotovo ====="