93 lines
3.5 KiB
Bash
93 lines
3.5 KiB
Bash
#!/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:-<zadna>}"
|
|
|
|
# --- 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 ====="
|