fix: 备份与恢复脚本深度修复
backup-db.sh: - 新增备份后 SQLite 文件有效性验证(scp 传输后检查) restore-db.sh (云端恢复): - 修复:验证用 docker cp + docker exec sqlite3,不再依赖宿主机 sqlite3 - 修复:先停止容器再替换数据库,防止写入冲突 - 修复:替换后删除 WAL/SHM 残留文件,防止旧日志与新库不匹配损坏
This commit is contained in:
parent
d65583f6df
commit
7c213873bb
10
backup-db.sh
10
backup-db.sh
|
|
@ -29,6 +29,16 @@ log "复制到本地..."
|
||||||
scp "txjp:/tmp/db-backup/assets-${TIMESTAMP}.db" "${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/issue-${TIMESTAMP}.db" "${LOCAL_DIR}/"
|
||||||
|
|
||||||
|
# 验证备份文件为有效 SQLite 数据库
|
||||||
|
log "验证备份完整性..."
|
||||||
|
for f in "${LOCAL_DIR}/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/issue-${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"
|
ssh txjp "rm -rf /tmp/db-backup"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,8 +155,10 @@ restore_cloud() {
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 2. 验证备份文件
|
# 2. 验证备份文件(通过临时容器,避免依赖宿主机 sqlite3)
|
||||||
if ! ssh txjp "sqlite3 ${BACKUP_PATH} 'SELECT count(*) FROM sqlite_master' > /dev/null 2>&1"; then
|
if ! ssh txjp "docker cp ${BACKUP_PATH} ${CONTAINER}:/tmp/restore-check.db 2>/dev/null && \
|
||||||
|
docker exec ${CONTAINER} sqlite3 /tmp/restore-check.db 'SELECT count(*) FROM sqlite_master' > /dev/null 2>&1 && \
|
||||||
|
docker exec ${CONTAINER} rm /tmp/restore-check.db"; then
|
||||||
echo "[错误] 备份文件不是有效的 SQLite 数据库"
|
echo "[错误] 备份文件不是有效的 SQLite 数据库"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -191,21 +193,29 @@ restore_cloud() {
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 5. 云端安全备份当前数据库
|
# 5. 停止容器(确保数据库不被写入,安全替换)
|
||||||
|
echo "[操作] 停止容器 ${CONTAINER}..."
|
||||||
|
ssh txjp "cd /root/docker/${PROJECT_DIR} && docker compose stop ${CONTAINER}"
|
||||||
|
|
||||||
|
# 6. 备份当前数据库(容器已停止,安全复制)
|
||||||
local SAFE_NAME="before-restore-$(date +%Y%m%d_%H%M%S).db"
|
local SAFE_NAME="before-restore-$(date +%Y%m%d_%H%M%S).db"
|
||||||
echo "[操作] 备份云端当前数据库..."
|
echo "[操作] 备份云端当前数据库..."
|
||||||
ssh txjp "docker cp ${CONTAINER}:${DB_PATH_IN_CONTAINER} /root/docker/db-backups/${SAFE_NAME}"
|
ssh txjp "docker cp ${CONTAINER}:${DB_PATH_IN_CONTAINER} /root/docker/db-backups/${SAFE_NAME}"
|
||||||
echo "[备份] 当前数据库已保存至云端: /root/docker/db-backups/${SAFE_NAME}"
|
echo "[备份] 当前数据库已保存至云端: /root/docker/db-backups/${SAFE_NAME}"
|
||||||
|
|
||||||
# 6. 复制备份文件到容器
|
# 7. 替换数据库
|
||||||
echo "[操作] 复制备份文件到容器..."
|
echo "[操作] 复制备份文件到容器..."
|
||||||
ssh txjp "docker cp ${BACKUP_PATH} ${CONTAINER}:${DB_PATH_IN_CONTAINER}"
|
ssh txjp "docker cp ${BACKUP_PATH} ${CONTAINER}:${DB_PATH_IN_CONTAINER}"
|
||||||
|
|
||||||
# 7. 重启容器
|
# 8. 删除残留 WAL/SHM 文件,防止旧日志与新数据库不匹配导致损坏
|
||||||
echo "[操作] 重启容器 ${CONTAINER}..."
|
echo "[操作] 清理残留 WAL/SHM 文件..."
|
||||||
ssh txjp "cd /root/docker/${PROJECT_DIR} && docker compose restart ${CONTAINER}"
|
ssh txjp "docker exec ${CONTAINER} rm -f ${DB_PATH_IN_CONTAINER}-shm ${DB_PATH_IN_CONTAINER}-wal" 2>/dev/null || true
|
||||||
|
|
||||||
# 8. 验证
|
# 9. 启动容器
|
||||||
|
echo "[操作] 启动容器 ${CONTAINER}..."
|
||||||
|
ssh txjp "cd /root/docker/${PROJECT_DIR} && docker compose start ${CONTAINER}"
|
||||||
|
|
||||||
|
# 10. 验证
|
||||||
sleep 3
|
sleep 3
|
||||||
echo ""
|
echo ""
|
||||||
echo "[验证] 恢复后数据:"
|
echo "[验证] 恢复后数据:"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue