ops: add backup verification script
This commit is contained in:
@@ -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
85
scripts/backup_verify.sh
Normal 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 "$@"
|
||||
Reference in New Issue
Block a user