Files
caiwuzongzhang/deploy/backup.sh
T

54 lines
2.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 在线热备:不停服备份 SQLite(backup API 保证一致性)+ files/ 原始文件目录。
# 用法:./backup.sh [备份根目录](默认 ../backups
# 保留策略:日备保留 30 天,每月 1 号的首份备份额外保留 12 个月(monthly/)。
# 建议宿主机 cron15 2 * * * /path/to/deploy/backup.sh >> /path/to/deploy/backup.log 2>&1
# 官方环境建议至少将 monthly/ 同步一份到异机/异盘。
set -euo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)"
DEST="${1:-$ROOT/../backups}"
CONTAINER="${CONTAINER:-caiwuzongzhang-app}"
STAMP="$(date +%Y%m%d-%H%M%S)"
DAY_DIR="$DEST/daily"
MONTH_DIR="$DEST/monthly"
mkdir -p "$DAY_DIR" "$MONTH_DIR"
# 1) SQLite 在线热备(容器内 python sqlite3 backup API,主库可继续写入)
# 备份文件写进数据卷 /app/data(宿主机 deploy/../data 可直接读取),避免
# read_only 容器 + tmpfs 下 docker cp 取不到文件的问题。
docker exec -i "$CONTAINER" python - <<'PY'
import os, sqlite3
src = sqlite3.connect(os.environ.get("APP_DB_PATH", "/app/data/app.db"))
dst = sqlite3.connect("/app/data/.backup-tmp.db")
src.backup(dst)
dst.close(); src.close()
print("hot-backup ok")
PY
mv "$ROOT/../data/.backup-tmp.db" "$DAY_DIR/app.db.$STAMP"
# 2) 原始文件目录打包(银行原始证据,只读复制,绝不改动)
tar -C "$ROOT/.." -czf "$DAY_DIR/files.$STAMP.tar.gz" data/files
# 3) 完整性自检:PRAGMA integrity_check + 关键计数
docker run --rm -v "$DAY_DIR/app.db.$STAMP:/check/app.db:ro" python:3.12-slim-bookworm \
python -c "
import sqlite3
c = sqlite3.connect('/check/app.db')
print('integrity:', c.execute('PRAGMA integrity_check').fetchone()[0])
for t in ('source_rows', 'transfer_match_decisions', 'period_close_runs', 'audit_log'):
try:
print(t, c.execute(f'SELECT COUNT(*) FROM {t}').fetchone()[0])
except sqlite3.OperationalError:
print(t, 'n/a')
"
# 4) 保留策略:日备 >30 天删除;每月 1 号留档 monthly/
find "$DAY_DIR" -name 'app.db.*' -mtime +30 -delete
find "$DAY_DIR" -name 'files.*.tar.gz' -mtime +30 -delete
if [ "$(date +%d)" = "01" ]; then
cp "$DAY_DIR/app.db.$STAMP" "$MONTH_DIR/app.db.$STAMP"
cp "$DAY_DIR/files.$STAMP.tar.gz" "$MONTH_DIR/files.$STAMP.tar.gz"
find "$MONTH_DIR" -mtime +365 -delete
fi
echo "backup complete: $DAY_DIR/app.db.$STAMP"