From db5fc39072c9cf302585f8417a0ec75479a1bfaa Mon Sep 17 00:00:00 2001 From: empty Date: Sat, 27 Dec 2025 12:37:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=B4=A6=E5=8F=B7?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=A2=9E=E9=87=8F=E5=90=8C=E6=AD=A5=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 支持 SSH 方式安全同步到远程服务器 - 支持 PM2/Docker/Docker Compose 多种部署方式 - 按 email 增量合并,不覆盖现有账号 --- sync-accounts.sh | 190 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100755 sync-accounts.sh diff --git a/sync-accounts.sh b/sync-accounts.sh new file mode 100755 index 0000000..4f3c212 --- /dev/null +++ b/sync-accounts.sh @@ -0,0 +1,190 @@ +#!/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. 远程服务器安装 jq:apt install jq 或 yum install jq +# + +set -e + +# ========== 配置区域 ========== +# 可以修改这些默认值,或通过命令行参数覆盖 +DEFAULT_SERVER="user@your-server.com" +DEFAULT_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 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 ""