64 lines
2.7 KiB
Bash
Executable File
64 lines
2.7 KiB
Bash
Executable File
#!/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"; }
|
||
|
||
log "开始备份云端数据库..."
|
||
|
||
# 备份前执行 WAL checkpoint,确保数据全部合并到 .db 主文件
|
||
log "执行 WAL checkpoint (assets)..."
|
||
ssh txjp "docker exec assets-ai node -e \"const D=require('better-sqlite3');const db=new D('/app/data/assets.db');db.pragma('wal_checkpoint(TRUNCATE)');db.close();\""
|
||
log "执行 WAL checkpoint (issue)..."
|
||
ssh txjp "docker exec issue-ai node -e \"const D=require('better-sqlite3');const db=new D('/app/data/issue.db');db.pragma('wal_checkpoint(TRUNCATE)');db.close();\""
|
||
log "执行 WAL checkpoint (LLDAP)..."
|
||
ssh txjp "docker exec lldap sqlite3 /data/users.db 'PRAGMA wal_checkpoint(TRUNCATE);' 2>/dev/null || true"
|
||
|
||
# 云端打包(使用 docker cp 从容器内复制,确保拿到真实数据而非旧宿主机文件)
|
||
ssh txjp "mkdir -p /tmp/db-backup && \
|
||
docker cp assets-ai:/app/data/assets.db /tmp/db-backup/assets-${TIMESTAMP}.db && \
|
||
docker cp issue-ai:/app/data/issue.db /tmp/db-backup/issue-${TIMESTAMP}.db && \
|
||
docker cp lldap:/data/users.db /tmp/db-backup/ldap-${TIMESTAMP}.db"
|
||
|
||
# 确保本地备份目录存在
|
||
mkdir -p "${LOCAL_DIR}"
|
||
|
||
# 云端留一份持久备份
|
||
CLOUD_DIR="/root/docker/db-backups"
|
||
ssh txjp "mkdir -p ${CLOUD_DIR} && \
|
||
cp /tmp/db-backup/assets-${TIMESTAMP}.db ${CLOUD_DIR}/assets-${TIMESTAMP}.db && \
|
||
cp /tmp/db-backup/issue-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db && \
|
||
cp /tmp/db-backup/ldap-${TIMESTAMP}.db ${CLOUD_DIR}/ldap-${TIMESTAMP}.db"
|
||
log "云端备份已保存至: ${CLOUD_DIR}"
|
||
|
||
# 复制到本地
|
||
log "复制到本地..."
|
||
mkdir -p "${LOCAL_DIR}"
|
||
scp "txjp:/tmp/db-backup/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/"
|
||
scp "txjp:/tmp/db-backup/issue-${TIMESTAMP}.db" "${LOCAL_DIR}/"
|
||
scp "txjp:/tmp/db-backup/ldap-${TIMESTAMP}.db" "${LOCAL_DIR}/"
|
||
|
||
# 验证备份文件为有效 SQLite 数据库
|
||
log "验证备份完整性..."
|
||
for f in "${LOCAL_DIR}/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/issue-${TIMESTAMP}.db" "${LOCAL_DIR}/ldap-${TIMESTAMP}.db"; do
|
||
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}/assets-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db ${CLOUD_DIR}/ldap-${TIMESTAMP}.db 2>/dev/null"
|
||
echo " 本地:"
|
||
ls -lh "${LOCAL_DIR}"/assets-${TIMESTAMP}.db "${LOCAL_DIR}"/issue-${TIMESTAMP}.db "${LOCAL_DIR}"/ldap-${TIMESTAMP}.db 2>/dev/null
|