website-scripts/backup/restore-full.sh

290 lines
9.2 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 restore-full.sh [备份文件名]
# 无参数则自动检测当前目录下的最新备份
set -e
BACKUP_DIR="/Users/niuniu/programs/docker/db-backups"
REMOTE_BASE="/root/docker"
log() { echo "[$(date '+%H:%M:%S')] $1"; }
warn() { echo "[$(date '+%H:%M:%S')] [警告] $1"; }
error() { echo "[$(date '+%H:%M:%S')] [错误] $1"; exit 1; }
# ============================================================
# 1. 选择备份文件
# ============================================================
if [[ -n "$1" ]]; then
BACKUP_FILE="$1"
else
echo ""
echo "=========================================="
echo " 可用的完整备份文件"
echo "=========================================="
echo ""
# 列出本地备份
if [[ -d "$BACKUP_DIR" ]]; then
local_files=$(ls -t ${BACKUP_DIR}/full-backup-*.tar.gz 2>/dev/null | head -10)
if [[ -n "$local_files" ]]; then
echo "本地备份:"
index=1
while IFS= read -r file; do
filename=$(basename "$file")
filesize=$(du -h "$file" | cut -f1)
echo " $index) $filename ($filesize)"
files[$index]="$file"
((index++))
done <<< "$local_files"
echo ""
fi
fi
# 列出云端备份
echo "云端备份:"
cloud_files=$(ssh txjp "ls -t /root/docker/db-backups/full-backup-*.tar.gz 2>/dev/null | head -10" 2>/dev/null || true)
if [[ -n "$cloud_files" ]]; then
while IFS= read -r file; do
filename=$(basename "$file")
echo " $index) [云端] $filename"
files[$index]="cloud:$file"
((index++))
done <<< "$cloud_files"
echo ""
fi
if [[ ${#files[@]} -eq 0 ]]; then
error "未找到任何备份文件"
fi
printf "请选择备份文件 (1-$((index-1))): "
read choice
if [[ -z "${files[$choice]}" ]]; then
error "无效选择"
fi
BACKUP_FILE="${files[$choice]}"
fi
# ============================================================
# 2. 下载云端备份到临时目录
# ============================================================
RESTORE_DIR="/tmp/restore-$$"
mkdir -p "$RESTORE_DIR"
if [[ "$BACKUP_FILE" == cloud:* ]]; then
cloud_path="${BACKUP_FILE#cloud:}"
log "从云端下载备份..."
scp "txjp:$cloud_path" "$RESTORE_DIR/"
BACKUP_FILE="$RESTORE_DIR/$(basename $cloud_path)"
fi
# ============================================================
# 3. 解压备份
# ============================================================
log "解压备份文件..."
cd "$RESTORE_DIR"
tar xzf "$BACKUP_FILE"
# 检测备份内容
BACKUP_CONTENT="$RESTORE_DIR/full-backup"
if [[ ! -d "$BACKUP_CONTENT" ]]; then
error "备份文件格式错误"
fi
log "备份内容:"
ls -la "$BACKUP_CONTENT/"
# ============================================================
# 4. 选择要恢复的站点
# ============================================================
echo ""
echo "=========================================="
echo " 选择要恢复的内容"
echo "=========================================="
echo ""
echo " 1) assets - 资产管理系统"
echo " 2) issue - 工单系统"
echo " 3) ldap - 用户目录服务"
echo " 4) gitea - 代码仓库"
echo " 5) monitor - 告警监控中心"
echo " 6) nginx - 反向代理配置"
echo " 7) 全部恢复"
echo ""
printf "请选择 (1-7): "
read site_choice
# ============================================================
# 5. 执行恢复
# ============================================================
restore_assets() {
log "恢复 assets 站点..."
# 恢复数据库
if [[ -f "$BACKUP_CONTENT/databases/assets.db" ]]; then
log "恢复 assets 数据库..."
scp "$BACKUP_CONTENT/databases/assets.db" txjp:/tmp/assets.db
ssh txjp "docker cp /tmp/assets.db assets-ai:/app/data/assets.db && rm /tmp/assets.db"
ssh txjp "docker restart assets-ai"
log "assets 数据库恢复完成"
fi
# 恢复配置
if [[ -d "$BACKUP_CONTENT/configs/assets-ai" ]]; then
log "恢复 assets 配置..."
ssh txjp "mkdir -p $REMOTE_BASE/assets-ai"
scp "$BACKUP_CONTENT/configs/assets-ai/"* txjp:$REMOTE_BASE/assets-ai/ 2>/dev/null || true
fi
# 恢复上传文件
if [[ -d "$BACKUP_CONTENT/uploads/assets-uploads" ]]; then
log "恢复 assets 上传文件..."
ssh txjp "mkdir -p $REMOTE_BASE/assets-ai/data"
scp -r "$BACKUP_CONTENT/uploads/assets-uploads/"* txjp:$REMOTE_BASE/assets-ai/data/uploads/ 2>/dev/null || true
fi
}
restore_issue() {
log "恢复 issue 站点..."
# 恢复数据库
if [[ -f "$BACKUP_CONTENT/databases/issue.db" ]]; then
log "恢复 issue 数据库..."
scp "$BACKUP_CONTENT/databases/issue.db" txjp:/tmp/issue.db
ssh txjp "docker cp /tmp/issue.db issue-ai:/app/data/issue.db && rm /tmp/issue.db"
ssh txjp "docker restart issue-ai"
log "issue 数据库恢复完成"
fi
# 恢复配置
if [[ -d "$BACKUP_CONTENT/configs/issue-ai" ]]; then
log "恢复 issue 配置..."
ssh txjp "mkdir -p $REMOTE_BASE/issue-ai"
scp "$BACKUP_CONTENT/configs/issue-ai/"* txjp:$REMOTE_BASE/issue-ai/ 2>/dev/null || true
fi
# 恢复上传文件
if [[ -d "$BACKUP_CONTENT/uploads/issue-uploads" ]]; then
log "恢复 issue 上传文件..."
ssh txjp "mkdir -p $REMOTE_BASE/issue-ai/data"
scp -r "$BACKUP_CONTENT/uploads/issue-uploads/"* txjp:$REMOTE_BASE/issue-ai/data/uploads/ 2>/dev/null || true
fi
# 恢复报告文件
if [[ -d "$BACKUP_CONTENT/uploads/issue-reports" ]]; then
log "恢复 issue 报告文件..."
ssh txjp "mkdir -p $REMOTE_BASE/issue-ai/data"
scp -r "$BACKUP_CONTENT/uploads/issue-reports/"* txjp:$REMOTE_BASE/issue-ai/data/reports/ 2>/dev/null || true
fi
}
restore_ldap() {
log "恢复 ldap 站点..."
# 恢复数据库
if [[ -f "$BACKUP_CONTENT/databases/ldap.db" ]]; then
log "恢复 ldap 数据库..."
scp "$BACKUP_CONTENT/databases/ldap.db" txjp:/tmp/ldap.db
ssh txjp "docker cp /tmp/ldap.db lldap:/data/users.db && rm /tmp/ldap.db"
ssh txjp "docker restart lldap"
log "ldap 数据库恢复完成"
fi
# 恢复配置
if [[ -d "$BACKUP_CONTENT/configs/ldap-ai" ]]; then
log "恢复 ldap 配置..."
ssh txjp "mkdir -p $REMOTE_BASE/ldap-ai"
scp "$BACKUP_CONTENT/configs/ldap-ai/"* txjp:$REMOTE_BASE/ldap-ai/ 2>/dev/null || true
fi
}
restore_gitea() {
log "恢复 gitea 站点..."
# 恢复数据库
if [[ -f "$BACKUP_CONTENT/databases/gitea.db" ]]; then
log "恢复 gitea 数据库..."
scp "$BACKUP_CONTENT/databases/gitea.db" txjp:/tmp/gitea.db
ssh txjp "docker cp /tmp/gitea.db gitea-ai:/data/gitea.db && rm /tmp/gitea.db"
fi
# 恢复代码仓库
if [[ -d "$BACKUP_CONTENT/gitea/git" ]]; then
log "恢复 gitea 代码仓库..."
ssh txjp "mkdir -p $REMOTE_BASE/gitea-ai/data"
scp -r "$BACKUP_CONTENT/gitea/git" txjp:$REMOTE_BASE/gitea-ai/data/
fi
# 恢复配置
if [[ -d "$BACKUP_CONTENT/gitea/conf" ]]; then
log "恢复 gitea 配置..."
ssh txjp "mkdir -p $REMOTE_BASE/gitea-ai/data/gitea"
scp -r "$BACKUP_CONTENT/gitea/conf" txjp:$REMOTE_BASE/gitea-ai/data/gitea/
fi
# 恢复 docker-compose
if [[ -d "$BACKUP_CONTENT/configs/gitea-ai" ]]; then
log "恢复 gitea docker-compose..."
scp "$BACKUP_CONTENT/configs/gitea-ai/"* txjp:$REMOTE_BASE/gitea-ai/ 2>/dev/null || true
fi
# 重启容器
ssh txjp "cd $REMOTE_BASE/gitea-ai && docker compose down && docker compose up -d"
log "gitea 恢复完成"
}
restore_nginx() {
log "恢复 nginx 配置..."
if [[ -d "$BACKUP_CONTENT/nginx" ]]; then
ssh txjp "mkdir -p $REMOTE_BASE/nginx-proxy-ai/conf.d"
scp "$BACKUP_CONTENT/nginx/"* txjp:$REMOTE_BASE/nginx-proxy-ai/conf.d/
ssh txjp "docker exec nginx-ai nginx -t && docker exec nginx-ai nginx -s reload"
log "nginx 配置恢复完成"
fi
}
restore_monitor() {
log "恢复 monitor 站点..."
if [[ -f "$BACKUP_CONTENT/databases/monitor.db" ]]; then
ssh txjp "docker cp $BACKUP_CONTENT/databases/monitor.db monitor-ai:/app/data/monitor.db"
log "monitor 数据库恢复完成"
else
warn "未找到 monitor 数据库备份"
fi
ssh txjp "cd $REMOTE_BASE/monitor-ai && docker compose down && docker compose up -d --build"
log "monitor 恢复完成"
}
# 执行恢复
case "$site_choice" in
1) restore_assets ;;
2) restore_issue ;;
3) restore_ldap ;;
4) restore_gitea ;;
5) restore_monitor ;;
6) restore_nginx ;;
7)
restore_assets
restore_issue
restore_ldap
restore_gitea
restore_monitor
restore_nginx
;;
*) error "无效选择" ;;
esac
# ============================================================
# 6. 清理临时文件
# ============================================================
log "清理临时文件..."
rm -rf "$RESTORE_DIR"
echo ""
log "恢复完成!"