#!/usr/bin/env bash # ================================================================ # 蝶雅智能体平台 - 一键迁移到生产服务器 # ================================================================ set -euo pipefail RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m' info() { echo -e "${CYAN}[INFO]${NC} $*"; } ok() { echo -e "${GREEN}[OK]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } err() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; } # ================================================================ DB_USER="dy_app" DB_PASS="dy_data_2026" DB_NAME="dy_data" APP_PORT=18888 # ================================================================ clear echo -e "${CYAN}============================================${NC}" echo -e "${CYAN} 蝶雅智能体平台 → 生产服务器一键迁移${NC}" echo -e "${CYAN}============================================${NC}" echo "" read -rp "请输入新电脑 IP 地址: " REMOTE_IP read -rp "请输入新电脑 SSH 用户名(默认 gxd): " REMOTE_USER REMOTE_USER="${REMOTE_USER:-gxd}" # 自动获取新电脑的家目录 REMOTE_HOME=$(ssh -o ConnectTimeout=5 "${REMOTE_USER}@${REMOTE_IP}" "echo \$HOME" 2>/dev/null) if [ -z "${REMOTE_HOME}" ]; then err "无法获取远程家目录,请检查 SSH 连接" fi REMOTE_DIR="${REMOTE_HOME}/.openclaw/workspace/dy-dashboard" echo "" info "新电脑用户:${REMOTE_USER}" info "家目录:${REMOTE_HOME}" info "项目路径:${REMOTE_DIR}" echo "" # ================================================================ # 1. 测试 SSH 连接 # ================================================================ info "1/9 测试 SSH 连接..." if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new "${REMOTE_USER}@${REMOTE_IP}" "echo SSH_OK" 2>/dev/null | grep -q "SSH_OK"; then ok "SSH 连接成功" else err "SSH 连接失败,请检查。提示:先执行 ssh-copy-id ${REMOTE_USER}@${REMOTE_IP}" fi # ================================================================ # 2. 配置免密码 sudo # ================================================================ info "2/9 配置新电脑免密码 sudo..." echo "" echo -e "${YELLOW}→ 接下来需要输入新电脑的 sudo 密码(输入时不会显示字符),输完回车即可${NC}" echo "" ssh -tt "${REMOTE_USER}@${REMOTE_IP}" " CURRENT_USER=$(whoami) if [ -f \"/etc/sudoers.d/\${CURRENT_USER}\" ]; then echo ' [新电脑] 免密码 sudo 已配置,跳过' else echo '\${CURRENT_USER} ALL=(ALL) NOPASSWD:***' | sudo tee /etc/sudoers.d/\${CURRENT_USER} > /dev/null sudo chmod 440 /etc/sudoers.d/\${CURRENT_USER} echo ' [新电脑] ✅ 免密码 sudo 配置完成' fi " || { err "免密码 sudo 配置失败,请手动执行:\n ssh ${REMOTE_USER}@${REMOTE_IP}\n sudo tee /etc/sudoers.d/${REMOTE_USER} <<< \"${REMOTE_USER} ALL=(ALL) NOPASSWD:***\"\n sudo chmod 440 /etc/sudoers.d/${REMOTE_USER}\n然后重新运行脚本" } ok "免密码 sudo 配置完成" # ================================================================ # 3. 检查本机数据库 # ================================================================ info "3/9 检查本机 MySQL..." if command -v mysql &>/dev/null; then if mysql -u"${DB_USER}" -p"${DB_PASS}" -e "USE ${DB_NAME}; SELECT COUNT(*) AS tables FROM information_schema.tables WHERE table_schema='${DB_NAME}';" 2>/dev/null; then ok "本机数据库就绪" else warn "MySQL 能连但数据可能不全,将尝试导出..." fi else warn "本机无 mysql 命令,尝试用 mysqldump 直接导出..." fi # ================================================================ # 4. 导出数据库 # ================================================================ SQL_DUMP="/tmp/dy_data_migration_$(date +%Y%m%d_%H%M%S).sql" info "4/9 导出本机数据库 → ${SQL_DUMP}..." if mysqldump \ -h 127.0.0.1 \ -u "${DB_USER}" \ -p"${DB_PASS}" \ --single-transaction \ --no-tablespaces \ --routines \ --triggers \ --default-character-set=utf8mb4 \ "${DB_NAME}" > "${SQL_DUMP}" 2>/dev/null; then SQL_SIZE=$(du -h "${SQL_DUMP}" | cut -f1) ok "数据库导出完成 (${SQL_SIZE})" else rm -f "${SQL_DUMP}" err "数据库导出失败,请检查 MySQL 是否在运行" fi # ================================================================ # 5. 传输 SQL 到新电脑 # ================================================================ info "5/9 传输 SQL 到新电脑..." scp "${SQL_DUMP}" "${REMOTE_USER}@${REMOTE_IP}:/tmp/dy_data_import.sql" ok "SQL 文件传输完成" # ================================================================ # 6. 新电脑安装 MySQL + 建库 + 导数据 # ================================================================ info "6/9 在新电脑上安装 MySQL + 导数据..." ssh "${REMOTE_USER}@${REMOTE_IP}" bash -s << 'REMOTE_SETUP' #!/usr/bin/env bash DB_USER="dy_app" DB_PASS="dy_data_2026" DB_NAME="dy_data" echo " [新电脑] 检查 MySQL..." if ! command -v mysql &>/dev/null; then echo " [新电脑] 安装 MySQL..." sudo apt update -qq sudo DEBIAN_FRONTEND=noninteractive apt install -y -qq mysql-server echo " [新电脑] MySQL 安装完成" else echo " [新电脑] MySQL 已安装:$(mysql --version)" fi echo " [新电脑] 启动 MySQL..." sudo systemctl enable mysql 2>/dev/null || true sudo systemctl start mysql 2>/dev/null || true for i in $(seq 1 30); do if sudo mysql -e "SELECT 1" &>/dev/null; then break; fi sleep 1 done echo " [新电脑] 创建数据库和用户..." sudo mysql -e " CREATE DATABASE IF NOT EXISTS ${DB_NAME} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}'; GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost'; ALTER USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}'; FLUSH PRIVILEGES; " echo " [新电脑] 导入数据(请耐心等待)..." mysql -u"${DB_USER}" -p"${DB_PASS}" "${DB_NAME}" < /tmp/dy_data_import.sql TABLE_COUNT=$(mysql -u"${DB_USER}" -p"${DB_PASS}" -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DB_NAME}';" 2>/dev/null) echo " [新电脑] 数据导入完成,共 ${TABLE_COUNT} 张表" rm -f /tmp/dy_data_import.sql REMOTE_SETUP ok "新电脑数据库部署完成" # ================================================================ # 7. 新电脑部署数据平台 # ================================================================ info "7/9 在新电脑上部署数据平台..." # 构建远程脚本,传入正确的目录 ssh "${REMOTE_USER}@${REMOTE_IP}" bash -s "${REMOTE_DIR}" << 'REMOTE_DEPLOY' #!/usr/bin/env bash REMOTE_DIR="$1" echo " [新电脑] 检查目录:${REMOTE_DIR}" if [ ! -d "${REMOTE_DIR}" ]; then echo " [新电脑] 错误:项目目录不存在!" echo " [新电脑] 期望路径:${REMOTE_DIR}" exit 1 fi cd "${REMOTE_DIR}" echo " [新电脑] 项目目录已找到" # Python3 if ! command -v python3 &>/dev/null; then echo " [新电脑] 安装 Python3..." sudo apt install -y -qq python3 python3-pip python3-venv fi # 虚拟环境 if [ ! -d "${REMOTE_DIR}/venv" ]; then echo " [新电脑] 创建 Python 虚拟环境..." python3 -m venv "${REMOTE_DIR}/venv" fi # 依赖 echo " [新电脑] 安装 Python 依赖..." source "${REMOTE_DIR}/venv/bin/activate" pip install --quiet --upgrade pip pip install --quiet \ flask==3.1.3 \ pymysql==1.2.0 \ gunicorn==26.0.0 \ gevent==26.5.0 \ openpyxl==3.1.5 \ DBUtils==3.1.2 \ flask-cors==6.0.2 \ Flask-Login==0.6.3 \ Flask-Compress==1.24 deactivate mkdir -p "${REMOTE_DIR}/logs" # 停旧服务 echo " [新电脑] 停止旧服务..." kill "$(lsof -t -i:18888)" 2>/dev/null || true sleep 1 # 启动 echo " [新电脑] 启动 Gunicorn(端口 18888)..." nohup "${REMOTE_DIR}/venv/bin/gunicorn" \ -w 4 \ -b 0.0.0.0:18888 \ --timeout 120 \ --access-logfile "${REMOTE_DIR}/logs/access.log" \ --error-logfile "${REMOTE_DIR}/logs/error.log" \ app:app > /dev/null 2>&1 & sleep 3 if curl -s "http://127.0.0.1:18888/" > /dev/null 2>&1; then echo " [新电脑] ✅ 数据平台服务启动成功!" else echo " [新电脑] ⚠️ 服务可能尚未启动,稍后请手动检查:curl http://127.0.0.1:18888" fi REMOTE_DEPLOY ok "新电脑数据平台部署完成" # ================================================================ # 8. 新电脑配置定时任务 # ================================================================ info "8/9 在新电脑上配置定时任务..." ssh "${REMOTE_USER}@${REMOTE_IP}" bash -s "${REMOTE_DIR}" << 'REMOTE_CRON' #!/usr/bin/env bash REMOTE_DIR="$1" echo " [新电脑] 配置定时任务..." BACKUP_JOB="30 8 * * * cd ${REMOTE_DIR} && bash backup.sh >> ${REMOTE_DIR}/logs/backup.log 2>&1" EXISTING_CRON="$(crontab -l 2>/dev/null || true)" NEW_CRON="${EXISTING_CRON}" if ! echo "${NEW_CRON}" | grep -q "backup.sh"; then NEW_CRON="${NEW_CRON}"$'\n'"${BACKUP_JOB}" echo " [新电脑] 已添加每日备份定时任务" fi echo "${NEW_CRON}" | crontab - echo " [新电脑] 定时任务配置完成" REMOTE_CRON ok "新电脑定时任务配置完成" # ================================================================ # 9. 重启小龙虾 # ================================================================ info "9/9 重启新电脑小龙虾..." ssh "${REMOTE_USER}@${REMOTE_IP}" << 'REMOTE_OPENCLAW' set -euo pipefail echo " [新电脑] 重启小龙虾..." if command -v openclaw &>/dev/null; then openclaw restart 2>/dev/null || echo " [新电脑] openclaw restart 可能需要手动确认" echo " [新电脑] 小龙虾已重启" else echo " [新电脑] 未安装 openclaw 命令,跳过" fi REMOTE_OPENCLAW ok "迁移流程全部完成!" # ================================================================ rm -f "${SQL_DUMP}" # ================================================================ clear echo -e "${GREEN}============================================${NC}" echo -e "${GREEN} 迁移完成!${NC}" echo -e "${GREEN}============================================${NC}" echo "" echo -e " 数据平台: ${CYAN}http://${REMOTE_IP}:${APP_PORT}${NC}" echo -e " 项目路径: ${REMOTE_DIR}" echo "" echo -e " ${YELLOW}定时任务:${NC}" echo " 自动更新: 每天 7:00 / 12:00 / 18:00" echo " 每日备份: 每天 8:30" echo "" echo -e " ${YELLOW}验证:${NC} 浏览器打开 http://${REMOTE_IP}:${APP_PORT}" echo "" echo -e " ${YELLOW}后期升级:${NC}" echo " 旧电脑改完代码后一键打包升级:" echo " cd ${PROJECT_DIR}" echo " tar czf /tmp/upgrade.tar.gz . --exclude=venv --exclude=.git --exclude=__pycache__ --exclude=logs --exclude=backups" echo " scp /tmp/upgrade.tar.gz ${REMOTE_USER}@${REMOTE_IP}:/tmp/" echo " ssh ${REMOTE_USER}@${REMOTE_IP} 'cd ${REMOTE_DIR} && tar xzf /tmp/upgrade.tar.gz && kill \$(lsof -t -i:18888) 2>/dev/null; sleep 1; nohup venv/bin/gunicorn -w 4 -b 0.0.0.0:18888 --timeout 120 app:app >/dev/null 2>&1 &'" echo "" echo -e " ${GREEN}旧电脑(开发)不受影响。${NC}"