#!/usr/bin/env bash # ============================================================= # 通过 rsync 把整个工程同步到远端服务器 # 用法: # 1. 复制 server.env.example -> server.env,填入主机/密码 # 2. ./sync-to-server.sh # 仅同步 # ./sync-to-server.sh up # 同步后在远端 docker compose build && up -d # ./sync-to-server.sh logs # 远端 docker compose logs # ============================================================= set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" # 读取服务器配置 if [ -f "$SCRIPT_DIR/server.env" ]; then # shellcheck disable=SC1091 set -a . "$SCRIPT_DIR/server.env" set +a elif [ -f "$SCRIPT_DIR/server.env.example" ]; then echo "[!] 未发现 server.env,请先 cp server.env.example server.env 并修改" exit 1 fi SERVER_HOST="${SERVER_HOST:?SERVER_HOST 未配置}" SERVER_USER="${SERVER_USER:-root}" SERVER_PORT="${SERVER_PORT:-22}" REMOTE_DIR="${REMOTE_DIR:-/root/integral-shop}" # ---------- 选择 SSH/rsync 通道 ---------- if [ -n "${SSHPASS:-}" ]; then if ! command -v sshpass >/dev/null 2>&1; then echo "[!] 检测到 SSHPASS 但未安装 sshpass" echo " macOS: brew install hudochenkov/sshpass/sshpass" echo " Linux: apt-get install -y sshpass" exit 1 fi export SSHPASS SSH=(sshpass -e ssh -p "$SERVER_PORT" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null) RSYNC_SSH="sshpass -e ssh -p $SERVER_PORT -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" else SSH=(ssh -p "$SERVER_PORT" -o StrictHostKeyChecking=no -o ServerAliveInterval=30) RSYNC_SSH="ssh -p $SERVER_PORT -o StrictHostKeyChecking=no -o ServerAliveInterval=30" fi remote() { "${SSH[@]}" "${SERVER_USER}@${SERVER_HOST}" "$@" } # ---------- 1. 远端目录准备 ---------- echo "[1/3] 准备远端目录 ${SERVER_USER}@${SERVER_HOST}:${REMOTE_DIR}" remote "mkdir -p '${REMOTE_DIR}'" # 优先使用 homebrew rsync(macOS 内置版本 2.6.9 太旧) RSYNC_BIN="/opt/homebrew/bin/rsync" [ -x "$RSYNC_BIN" ] || RSYNC_BIN="rsync" # ---------- 2. rsync ---------- echo "[2/3] rsync ${PROJECT_ROOT}/ -> ${SERVER_USER}@${SERVER_HOST}:${REMOTE_DIR}/" "$RSYNC_BIN" -avz --delete --partial \ -e "$RSYNC_SSH" \ --exclude '.git/' \ --exclude '.DS_Store' \ --exclude '*.log' \ --exclude '**/.idea/' \ --exclude '**/.cursor/' \ --exclude '**/.vscode/' \ --exclude '**/node_modules/' \ --exclude '**/target/' \ --exclude '**/unpackage/cache/' \ --exclude '**/unpackage/dist/dev/' \ --exclude 'integral-resell/houtai/runtime/logs/' \ --exclude 'integral-resell/houtai/runtime/sessions/' \ --exclude 'integral-resell/houtai/runtime/login/' \ --exclude 'integral-resell/houtai/runtime/webman.pid' \ --exclude 'single-shop-22/backend/logs/' \ --exclude 'single-shop-22/backend/crmebimage/' \ --exclude 'single-shop-22/backend-adminend/dist/' \ --exclude 'MER-2.2_2601/' \ --exclude 'db/mysql-recover-20260514/' \ --exclude 'db/yangtangyoupin.sql' \ --exclude 'deploy/docker/.env' \ --exclude 'deploy/docker/integral-resell/.env' \ --exclude 'deploy/docker/scripts/server.env' \ "${PROJECT_ROOT}/" "${SERVER_USER}@${SERVER_HOST}:${REMOTE_DIR}/" # ---------- 3. 远端 env 文件提示 ---------- echo "[3/3] 检查远端环境文件" remote "test -f ${REMOTE_DIR}/deploy/docker/.env || echo '[!] 远端缺少 deploy/docker/.env,请按下面提示创建'" remote "test -f ${REMOTE_DIR}/deploy/docker/integral-resell/.env || echo '[!] 远端缺少 deploy/docker/integral-resell/.env'" echo echo "===============================================" echo " rsync 完成" echo " 远端目录: ${REMOTE_DIR}" echo "===============================================" # ---------- 后续动作 ---------- case "${1:-${AUTO_UP:-}}" in up|yes|YES) echo "[远端] 执行 docker compose build && up -d" "$SCRIPT_DIR/remote-up.sh" up ;; build) "$SCRIPT_DIR/remote-up.sh" build ;; logs) shift || true "$SCRIPT_DIR/remote-up.sh" logs "$@" ;; "") echo "下一步:" echo " $0 up # 同步并启动" echo " $0 build # 仅构建" echo " $0 logs # 查看日志" ;; *) echo "未知参数: $1" exit 2 ;; esac