website-scripts/backup/backup-db.sh

99 lines
2.9 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.

#!/bin/bash
# 云端数据库一键备份脚本
# 用法bash backup-db.sh
set -e
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOCAL_DIR="/Users/niuniu/programs/docker/db-backups"
log() { echo "[$(date '+%H:%M:%S')] $1"; }
# 自动发现含数据库的站点
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DB_SITES=""
for dir in "$PROJECT_ROOT"/*-ai/; do
site=$(basename "$dir")
[[ "$site" == "nginx-proxy-ai" ]] && continue
[ -f "$dir/docker-compose.yml" ] || continue
grep -qE "\.db|DATABASE_PATH|sqlite" "$dir/docker-compose.yml" 2>/dev/null || continue
DB_SITES="$DB_SITES $site"
done
log "发现数据库站点:${DB_SITES}"
log "开始备份云端数据库..."
# 站点 → 容器名 + DB路径 映射(自动推导:<site> → <site>:/app/data/<site去掉-ai>.db
# LLDAP/gitea 容器名特殊,显式声明
declare -A DB_CONTAINERS=([ldap]="lldap:/data/users.db" [gitea]="gitea-ai:/data/gitea.db" [oa]="")
# 并行 WAL checkpoint
for site in $DB_SITES; do
[[ "$site" == "oa" ]] && continue # OA 无独立 DB
if [[ -n "${DB_CONTAINERS[$site]}" ]]; then
cname="${DB_CONTAINERS[$site]%%:*}"
else
cname="${site}" # assets-ai / issue-ai / monitor-ai
fi
log "WAL checkpoint: ${site} (${cname})..."
ssh txjp "docker exec ${cname} sqlite3 /app/data/*.db 'PRAGMA wal_checkpoint(TRUNCATE);' 2>/dev/null || true" &
done
wait
# 云端打包
ssh txjp "mkdir -p /tmp/db-backup"
for site in $DB_SITES; do
[[ "$site" == "oa" ]] && continue
if [[ -n "${DB_CONTAINERS[$site]}" ]]; then
cname="${DB_CONTAINERS[$site]%%:*}"
dbpath="${DB_CONTAINERS[$site]##*:}"
else
cname="${site}"
short="${site%-ai}" # assets-ai → assets
dbpath="/app/data/${short}.db"
fi
log "备份 ${site} (${cname}:${dbpath})..."
ssh txjp "docker cp ${cname}:${dbpath} /tmp/db-backup/${site}-${TIMESTAMP}.db"
done
# 确保本地备份目录存在
mkdir -p "${LOCAL_DIR}"
# 云端留一份持久备份
CLOUD_DIR="/root/docker/db-backups"
ssh txjp "mkdir -p ${CLOUD_DIR}"
for site in $DB_SITES; do
[[ "$site" == "oa" ]] && continue
ssh txjp "cp /tmp/db-backup/${site}-${TIMESTAMP}.db ${CLOUD_DIR}/"
done
log "云端备份已保存至: ${CLOUD_DIR}"
# 复制到本地
log "复制到本地..."
mkdir -p "${LOCAL_DIR}"
for site in $DB_SITES; do
[[ "$site" == "oa" ]] && continue
scp "txjp:/tmp/db-backup/${site}-${TIMESTAMP}.db" "${LOCAL_DIR}/"
done
# 验证备份文件为有效 SQLite 数据库
log "验证备份完整性..."
for site in $DB_SITES; do
[[ "$site" == "oa" ]] && continue
f="${LOCAL_DIR}/${site}-${TIMESTAMP}.db"
if ! sqlite3 "$f" "SELECT count(*) FROM sqlite_master" > /dev/null 2>&1; then
echo "[错误] 备份文件无效或损坏: $f"
exit 1
fi
done
log "备份文件验证通过"
# 清理云端临时文件
ssh txjp "rm -rf /tmp/db-backup"
log "备份完成:${TIMESTAMP}"
echo " 云端: ${CLOUD_DIR}/"
ssh txjp "ls -lh ${CLOUD_DIR}/*-${TIMESTAMP}.db 2>/dev/null"
echo " 本地:"
ls -lh "${LOCAL_DIR}"/*-${TIMESTAMP}.db 2>/dev/null