feat: 添加账号配置增量同步脚本
- 支持 SSH 方式安全同步到远程服务器 - 支持 PM2/Docker/Docker Compose 多种部署方式 - 按 email 增量合并,不覆盖现有账号
This commit is contained in:
190
sync-accounts.sh
Executable file
190
sync-accounts.sh
Executable file
@@ -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 ""
|
||||||
Reference in New Issue
Block a user