ops: add backup verification script
Some checks failed
CI / pytest (Python 3.10) (push) Has been cancelled
CI / pytest (Python 3.11) (push) Has been cancelled
CI / pytest (Python 3.12) (push) Has been cancelled

This commit is contained in:
Hermes Agent
2026-06-14 19:36:57 +08:00
parent ccf93c0b15
commit 2f4eabf681
2 changed files with 91 additions and 1 deletions

View File

@@ -70,7 +70,6 @@
## 6. 当前缺口
- 尚无自动化备份脚本
- 尚无恢复演练脚本
- 尚无定时任务
- 尚无备份完整性校验
@@ -80,3 +79,9 @@
2. 至少在临时目录恢复一次可读数据库
3. 明确密钥存放位置和负责人
4. 不得再使用“Git 备份即可恢复系统”作为对外或内部结论
## 8. 当前已落地产物
- `scripts/backup_verify.sh`
- 可复制当前 SQLite 数据库与示例报告到临时目录
- 可验证复制后的数据库可读、表可枚举、报告文件可见

85
scripts/backup_verify.sh Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
VERIFY_DIR="${1:-$(mktemp -d /tmp/gaokao-backup-verify-XXXXXX)}"
ADMIN_DB="${GAOKAO_DB_PATH:-${ROOT_DIR}/data/orders/admin.db}"
ORDERS_DB="${GAOKAO_ORDERS_DB_PATH:-${ROOT_DIR}/data/orders.db}"
SHARE_DB="${GAOKAO_SHARE_DB_PATH:-${ROOT_DIR}/data/share/short_links.db}"
SHARE_REPORT_DIR="${GAOKAO_SHARE_REPORT_DIR:-${ROOT_DIR}/data/share/reports}"
EXAMPLE_REPORT_DIR="${ROOT_DIR}/data/examples"
log() {
printf '[backup-verify] %s\n' "$1"
}
copy_if_exists() {
local src="$1"
local dest_dir="$2"
if [[ -f "$src" ]]; then
mkdir -p "$dest_dir"
cp "$src" "$dest_dir/"
log "copied file: $src"
else
log "skip missing file: $src"
fi
}
copy_dir_if_exists() {
local src="$1"
local dest_dir="$2"
if [[ -d "$src" ]]; then
mkdir -p "$dest_dir"
cp -R "$src" "$dest_dir/"
log "copied directory: $src"
else
log "skip missing directory: $src"
fi
}
verify_sqlite_file() {
local db_path="$1"
if [[ ! -f "$db_path" ]]; then
return 0
fi
python3 - <<'PY' "$db_path"
import sqlite3
import sys
from pathlib import Path
p = Path(sys.argv[1])
conn = sqlite3.connect(p)
try:
cur = conn.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
tables = [row[0] for row in cur.fetchall()]
print(f"sqlite_ok path={p} tables={','.join(tables) if tables else 'none'}")
finally:
conn.close()
PY
}
main() {
mkdir -p "$VERIFY_DIR"
log "verify dir: $VERIFY_DIR"
copy_if_exists "$ADMIN_DB" "$VERIFY_DIR/db"
copy_if_exists "$ORDERS_DB" "$VERIFY_DIR/db"
copy_if_exists "$SHARE_DB" "$VERIFY_DIR/db"
copy_dir_if_exists "$SHARE_REPORT_DIR" "$VERIFY_DIR/files"
copy_dir_if_exists "$EXAMPLE_REPORT_DIR" "$VERIFY_DIR/files"
log "verifying copied sqlite files"
if [[ -d "$VERIFY_DIR/db" ]]; then
while IFS= read -r -d '' db_file; do
verify_sqlite_file "$db_file"
done < <(find "$VERIFY_DIR/db" -type f -name '*.db' -print0 | sort -z)
fi
log "verifying copied report artifacts"
if [[ -d "$VERIFY_DIR/files" ]]; then
find "$VERIFY_DIR/files" -type f | sort | sed 's#^#[backup-verify] artifact: #'
fi
log "backup verification finished"
}
main "$@"