Files
droid2api/sync-accounts.sh
empty 5bdbc35875 feat: sync-accounts.sh 添加 Docker 镜像版本检测
- 检测远程容器是否支持多账号功能
- 版本过旧时给出更新镜像的具体命令
- 避免配置同步后无法生效的问题
2025-12-27 13:54:22 +08:00

236 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
#
# sync-accounts.sh - 账号配置增量同步脚本
#
# 用途:从本地机器增量同步 accounts.json 到远程无头服务器
#
# 使用方式:
# ./sync-accounts.sh # 使用默认配置
# ./sync-accounts.sh user@server.com # 指定服务器
# ./sync-accounts.sh user@server.com /path/to/droid2api # 指定路径
#
# 前置要求:
# 1. 配置 SSH 免密登录ssh-copy-id user@server.com
# 2. 远程服务器安装 jqapt install jq 或 yum install jq
#
set -e
# ========== 配置区域 ==========
# 优先从 .env 文件读取,可通过环境变量或命令行参数覆盖
# 加载 .env 文件(如果存在)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -f "$SCRIPT_DIR/.env" ]]; then
set -a # 自动导出变量
source "$SCRIPT_DIR/.env"
set +a
fi
# 配置项(优先级:命令行参数 > 环境变量 > 默认值)
DEFAULT_SERVER="${SYNC_SERVER:-user@your-server.com}"
DEFAULT_REMOTE_PATH="${SYNC_REMOTE_PATH:-/opt/droid2api}"
LOCAL_FILE="accounts.json"
# 部署方式: pm2 | docker | docker-compose | none
DEPLOY_TYPE="${DEPLOY_TYPE:-docker-compose}"
DOCKER_SERVICE_NAME="${DOCKER_SERVICE_NAME:-droid2api}"
PM2_APP_NAME="${PM2_APP_NAME:-droid2api}"
# ==============================
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# 解析命令行参数
SERVER="${1:-$DEFAULT_SERVER}"
REMOTE_PATH="${2:-$DEFAULT_REMOTE_PATH}"
REMOTE_FILE="$REMOTE_PATH/accounts.json"
# 显示帮助
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
echo "用法: $0 [user@server] [remote_path]"
echo ""
echo "环境变量:"
echo " DEPLOY_TYPE 部署方式: pm2 | docker | docker-compose | none (默认: docker-compose)"
echo " DOCKER_SERVICE_NAME Docker 服务名 (默认: droid2api)"
echo " PM2_APP_NAME PM2 应用名 (默认: droid2api)"
echo ""
echo "示例:"
echo " $0 root@192.168.1.100 /opt/droid2api"
echo " DEPLOY_TYPE=pm2 $0 user@server.com"
exit 0
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " 📦 账号配置增量同步工具"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# 检查本地文件是否存在
if [[ ! -f "$LOCAL_FILE" ]]; then
log_error "本地文件 $LOCAL_FILE 不存在"
log_info "请先运行 'node add-account.js' 添加账号"
exit 1
fi
# 显示连接信息
log_info "目标服务器: $SERVER"
log_info "远程路径: $REMOTE_FILE"
log_info "部署方式: $DEPLOY_TYPE"
echo ""
# 创建临时目录
TEMP_DIR=$(mktemp -d)
trap "rm -rf $TEMP_DIR" EXIT
# Step 1: 下载远程现有配置
log_info "正在获取远程现有配置..."
if ssh "$SERVER" "test -f $REMOTE_FILE" 2>/dev/null; then
scp -q "$SERVER:$REMOTE_FILE" "$TEMP_DIR/remote_accounts.json"
REMOTE_COUNT=$(jq '.accounts | length' "$TEMP_DIR/remote_accounts.json" 2>/dev/null || echo 0)
log_success "远程现有 $REMOTE_COUNT 个账号"
else
log_warn "远程配置不存在,将创建新文件"
echo '{"accounts":[],"settings":{}}' > "$TEMP_DIR/remote_accounts.json"
REMOTE_COUNT=0
fi
# Step 1.5: 检测 Docker 镜像版本(仅 docker-compose 模式)
if [[ "$DEPLOY_TYPE" == "docker-compose" ]]; then
log_info "正在检测远程镜像版本..."
# 检查远程 auth.js 是否包含多账号检测逻辑
MULTI_ACCOUNT_SUPPORT=$(ssh "$SERVER" "docker exec $DOCKER_SERVICE_NAME cat /app/auth.js 2>/dev/null | grep -c 'accounts.json' || echo 0" 2>/dev/null || echo "error")
if [[ "$MULTI_ACCOUNT_SUPPORT" == "error" || "$MULTI_ACCOUNT_SUPPORT" == "" ]]; then
log_warn "无法检测镜像版本(容器可能未运行)"
elif [[ "$MULTI_ACCOUNT_SUPPORT" == "0" ]]; then
echo ""
echo "══════════════════════════════════════════════════════════════"
log_error "⚠️ 远程镜像版本过旧,不支持多账号功能!"
echo "══════════════════════════════════════════════════════════════"
echo ""
log_info "请在服务器上执行以下命令更新镜像:"
echo ""
echo " cd $REMOTE_PATH"
echo " git pull origin main"
echo " docker compose build --no-cache"
echo " docker compose up -d"
echo ""
log_info "更新完成后,重新运行本脚本同步配置。"
echo ""
read -p "是否继续同步配置?(不推荐) (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_warn "已取消同步"
exit 0
fi
else
log_success "远程镜像支持多账号功能"
fi
fi
# Step 2: 显示本地账号数量
LOCAL_COUNT=$(jq '.accounts | length' "$LOCAL_FILE")
log_info "本地现有 $LOCAL_COUNT 个账号"
# Step 3: 合并配置(按 email 去重,本地优先)
log_info "正在合并配置..."
jq -s '
# 使用第一个文件(远程)的 accounts 作为基础
(.[0].accounts // []) as $remote |
# 使用第二个文件(本地)的 accounts
(.[1].accounts // []) as $local |
# 获取远程账号的 email 列表
($remote | map(.email)) as $remote_emails |
# 过滤出本地新增的账号email 不在远程列表中的)
($local | map(select(.email as $e | $remote_emails | index($e) | not))) as $new_local |
# 更新远程已存在的账号(用本地数据覆盖同 email 的远程账号)
($remote | map(
. as $r |
($local | map(select(.email == $r.email)) | .[0]) as $l |
if $l then $l else $r end
)) as $updated_remote |
# 合并:更新后的远程 + 本地新增
{
accounts: ($updated_remote + $new_local),
settings: (.[1].settings // .[0].settings // {}),
last_updated: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))
}
' "$TEMP_DIR/remote_accounts.json" "$LOCAL_FILE" > "$TEMP_DIR/merged_accounts.json"
MERGED_COUNT=$(jq '.accounts | length' "$TEMP_DIR/merged_accounts.json")
NEW_COUNT=$((MERGED_COUNT - REMOTE_COUNT))
if [[ $NEW_COUNT -gt 0 ]]; then
log_success "新增 $NEW_COUNT 个账号,合并后共 $MERGED_COUNT 个账号"
else
log_info "无新增账号,共 $MERGED_COUNT 个账号"
fi
# Step 4: 显示账号列表
echo ""
log_info "合并后的账号列表:"
echo "──────────────────────────────────────────────────────────────"
jq -r '.accounts[] | " \(.status == "active" | if . then "🟢" else "🔴" end) \(.email // .name) [\(.id)]"' "$TEMP_DIR/merged_accounts.json"
echo "──────────────────────────────────────────────────────────────"
echo ""
# Step 5: 确认上传
read -p "确认上传到服务器? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_warn "已取消"
exit 0
fi
# Step 6: 上传合并后的配置
log_info "正在上传配置..."
scp -q "$TEMP_DIR/merged_accounts.json" "$SERVER:$REMOTE_FILE"
log_success "配置已上传"
# Step 7: 重启服务(根据部署方式)
echo ""
case "$DEPLOY_TYPE" in
pm2)
log_info "正在重启 PM2 服务..."
ssh "$SERVER" "pm2 restart $PM2_APP_NAME" 2>/dev/null && \
log_success "PM2 服务已重启" || \
log_warn "PM2 重启失败,请手动重启"
;;
docker)
log_info "正在重启 Docker 容器..."
ssh "$SERVER" "docker restart $DOCKER_SERVICE_NAME" 2>/dev/null && \
log_success "Docker 容器已重启" || \
log_warn "Docker 重启失败,请手动重启"
;;
docker-compose)
log_info "正在重启 Docker Compose 服务..."
ssh "$SERVER" "cd $REMOTE_PATH && docker compose restart" 2>/dev/null && \
log_success "Docker Compose 服务已重启" || \
log_warn "Docker Compose 重启失败,请手动重启"
;;
none)
log_warn "已跳过服务重启,请手动重启服务以生效"
;;
*)
log_warn "未知的部署方式: $DEPLOY_TYPE,请手动重启服务"
;;
esac
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_success "同步完成!"
echo "═══════════════════════════════════════════════════════════════"
echo ""