Files
droid2api/sync-accounts.sh
empty 52ea5945eb refactor: sync-accounts.sh 配置改为从 .env 读取
- 自动加载脚本目录下的 .env 文件
- 新增 SYNC_SERVER, SYNC_REMOTE_PATH 等环境变量
- 更新 .env.example 添加同步配置示例
2025-12-27 12:47:08 +08:00

201 lines
7.4 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 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 ""