125 lines
5.6 KiB
Bash
Executable File
125 lines
5.6 KiB
Bash
Executable File
#!/bin/bash
|
||
# 完整灾难恢复备份脚本
|
||
# 包含:数据库、代码仓库、用户数据、配置文件、SSL证书
|
||
# 用法:bash backup-full.sh
|
||
|
||
set -e
|
||
|
||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||
LOCAL_DIR="/Users/niuniu/programs/docker/db-backups"
|
||
BACKUP_NAME="full-backup-${TIMESTAMP}"
|
||
|
||
log() { echo "[$(date '+%H:%M:%S')] $1"; }
|
||
warn() { echo "[$(date '+%H:%M:%S')] [警告] $1"; }
|
||
|
||
log "开始完整灾难恢复备份..."
|
||
|
||
# ============================================================
|
||
# 1. 数据库备份(WAL checkpoint + docker cp)
|
||
# ============================================================
|
||
log "执行 WAL checkpoint..."
|
||
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();\"" 2>/dev/null || warn "assets checkpoint 失败"
|
||
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();\"" 2>/dev/null || warn "issue checkpoint 失败"
|
||
ssh txjp "docker exec lldap sqlite3 /data/users.db 'PRAGMA wal_checkpoint(TRUNCATE);'" 2>/dev/null || warn "ldap checkpoint 失败"
|
||
|
||
log "导出数据库..."
|
||
ssh txjp "mkdir -p /tmp/full-backup/databases && \
|
||
docker cp assets-ai:/app/data/assets.db /tmp/full-backup/databases/assets.db && \
|
||
docker cp issue-ai:/app/data/issue.db /tmp/full-backup/databases/issue.db && \
|
||
docker cp lldap:/data/users.db /tmp/full-backup/databases/ldap.db && \
|
||
docker cp gitea-ai:/data/gitea.db /tmp/full-backup/databases/gitea.db"
|
||
|
||
# ============================================================
|
||
# 2. Gitea 代码仓库 + 配置
|
||
# ============================================================
|
||
log "备份 Gitea 代码仓库..."
|
||
ssh txjp "mkdir -p /tmp/full-backup/gitea && \
|
||
cp -a /root/docker/gitea-ai/data/git /tmp/full-backup/gitea/ && \
|
||
cp -a /root/docker/gitea-ai/data/gitea/conf /tmp/full-backup/gitea/ 2>/dev/null || true"
|
||
|
||
# ============================================================
|
||
# 3. 用户上传文件
|
||
# ============================================================
|
||
log "备份用户上传文件..."
|
||
ssh txjp "mkdir -p /tmp/full-backup/uploads && \
|
||
cp -a /root/docker/assets-ai/data/uploads /tmp/full-backup/uploads/assets-uploads 2>/dev/null || true && \
|
||
cp -a /root/docker/issue-ai/data/uploads /tmp/full-backup/uploads/issue-uploads 2>/dev/null || true && \
|
||
cp -a /root/docker/issue-ai/data/reports /tmp/full-backup/uploads/issue-reports 2>/dev/null || true"
|
||
|
||
# ============================================================
|
||
# 4. Nginx 配置
|
||
# ============================================================
|
||
log "备份 Nginx 配置..."
|
||
ssh txjp "mkdir -p /tmp/full-backup/nginx && \
|
||
cp -a /root/docker/nginx-proxy-ai/conf.d/* /tmp/full-backup/nginx/ 2>/dev/null || true"
|
||
|
||
# ============================================================
|
||
# 5. 各站点 docker-compose.yml + .env
|
||
# ============================================================
|
||
log "备份站点配置文件..."
|
||
ssh txjp "mkdir -p /tmp/full-backup/configs && \
|
||
for site in assets-ai issue-ai oa-ai ldap-ai gitea-ai; do \
|
||
mkdir -p /tmp/full-backup/configs/\$site && \
|
||
cp /root/docker/\$site/docker-compose.yml /tmp/full-backup/configs/\$site/ 2>/dev/null || true && \
|
||
cp /root/docker/\$site/.env /tmp/full-backup/configs/\$site/ 2>/dev/null || true && \
|
||
cp /root/docker/\$site/Dockerfile /tmp/full-backup/configs/\$site/ 2>/dev/null || true; \
|
||
done"
|
||
|
||
# ============================================================
|
||
# 6. SSL 证书
|
||
# ============================================================
|
||
log "备份 SSL 证书..."
|
||
ssh txjp "mkdir -p /tmp/full-backup/ssl && \
|
||
cp -a /etc/letsencrypt/live /tmp/full-backup/ssl/ 2>/dev/null || true && \
|
||
cp -a /etc/letsencrypt/archive /tmp/full-backup/ssl/ 2>/dev/null || true && \
|
||
cp -a /etc/letsencrypt/renewal /tmp/full-backup/ssl/ 2>/dev/null || true"
|
||
|
||
# ============================================================
|
||
# 7. 打包压缩
|
||
# ============================================================
|
||
log "打包压缩..."
|
||
ssh txjp "cd /tmp && tar czf ${BACKUP_NAME}.tar.gz full-backup/ && rm -rf /tmp/full-backup"
|
||
|
||
# ============================================================
|
||
# 8. 复制到本地
|
||
# ============================================================
|
||
log "复制到本地..."
|
||
mkdir -p "${LOCAL_DIR}"
|
||
scp "txjp:/tmp/${BACKUP_NAME}.tar.gz" "${LOCAL_DIR}/"
|
||
|
||
# ============================================================
|
||
# 9. 云端保留一份
|
||
# ============================================================
|
||
CLOUD_DIR="/root/docker/db-backups"
|
||
ssh txjp "mkdir -p ${CLOUD_DIR} && cp /tmp/${BACKUP_NAME}.tar.gz ${CLOUD_DIR}/"
|
||
log "云端备份已保存至: ${CLOUD_DIR}"
|
||
|
||
# ============================================================
|
||
# 10. 清理云端临时文件
|
||
# ============================================================
|
||
ssh txjp "rm -f /tmp/${BACKUP_NAME}.tar.gz"
|
||
|
||
# ============================================================
|
||
# 11. 验证备份
|
||
# ============================================================
|
||
log "验证备份完整性..."
|
||
cd "${LOCAL_DIR}"
|
||
if tar tzf "${BACKUP_NAME}.tar.gz" > /dev/null 2>&1; then
|
||
log "备份文件验证通过"
|
||
else
|
||
echo "[错误] 备份文件损坏"
|
||
exit 1
|
||
fi
|
||
|
||
# 显示备份内容
|
||
log "备份内容清单:"
|
||
tar tzf "${BACKUP_NAME}.tar.gz" | head -30
|
||
|
||
echo ""
|
||
log "备份完成:${TIMESTAMP}"
|
||
echo " 文件: ${LOCAL_DIR}/${BACKUP_NAME}.tar.gz"
|
||
echo " 大小: $(du -h ${LOCAL_DIR}/${BACKUP_NAME}.tar.gz | cut -f1)"
|
||
echo ""
|
||
echo " 云端: ${CLOUD_DIR}/${BACKUP_NAME}.tar.gz"
|
||
ssh txjp "ls -lh ${CLOUD_DIR}/${BACKUP_NAME}.tar.gz 2>/dev/null"
|