#!/bin/bash # 3D 家具安装展示系统 - 远程部署脚本 # 适用于: 从管理机远程部署到目标设备 # # 使用方法: # chmod +x scripts/remote-deploy.sh # ./scripts/remote-deploy.sh set -e # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 打印带颜色的消息 print_info() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # 打印欢迎信息 print_welcome() { echo "" echo "==========================================" echo " 3D 家具安装展示系统" echo " 远程部署脚本 v1.0" echo "==========================================" echo "" } # 打印使用说明 print_usage() { echo "使用方法:" echo " $0 [options]" echo "" echo "参数:" echo " target-host 目标设备的 IP 地址或主机名" echo " username SSH 登录用户名" echo "" echo "选项:" echo " -p, --port SSH 端口 (默认: 22)" echo " -k, --key SSH 私钥文件路径" echo " -m, --mode 部署模式 (standard/lightweight/auto)" echo " --silent 静默模式,使用默认配置" echo "" echo "示例:" echo " $0 192.168.1.100 admin" echo " $0 192.168.1.100 admin -p 2222 -k ~/.ssh/id_rsa" echo " $0 192.168.1.100 admin --mode lightweight" } # 解析命令行参数 parse_arguments() { if [ $# -lt 2 ]; then print_error "参数不足" print_usage exit 1 fi TARGET_HOST=$1 USERNAME=$2 shift 2 # 默认值 SSH_PORT=22 SSH_KEY="" DEPLOYMENT_MODE="auto" SILENT_MODE=false # 解析选项 while [[ $# -gt 0 ]]; do case $1 in -p|--port) SSH_PORT="$2" shift 2 ;; -k|--key) SSH_KEY="$2" shift 2 ;; -m|--mode) DEPLOYMENT_MODE="$2" shift 2 ;; --silent) SILENT_MODE=true shift ;; -h|--help) print_usage exit 0 ;; *) print_error "未知选项: $1" print_usage exit 1 ;; esac done } # 构建 SSH 命令 build_ssh_command() { SSH_CMD="ssh -p $SSH_PORT" if [ -n "$SSH_KEY" ]; then SSH_CMD="$SSH_CMD -i $SSH_KEY" fi SSH_CMD="$SSH_CMD $USERNAME@$TARGET_HOST" } # 测试 SSH 连接 test_ssh_connection() { print_info "测试 SSH 连接到 $TARGET_HOST..." if $SSH_CMD "echo 'Connection test'" &> /dev/null; then print_success "SSH 连接成功" return 0 else print_error "SSH 连接失败,请检查:" echo " - 目标主机是否可达" echo " - SSH 服务是否运行" echo " - 用户名和密码/密钥是否正确" echo " - 防火墙设置" exit 1 fi } # 检测远程系统 detect_remote_system() { print_info "检测远程系统..." # 检测操作系统 OS_TYPE=$($SSH_CMD "uname -s") print_info "操作系统: $OS_TYPE" # 检测 Docker if $SSH_CMD "command -v docker" &> /dev/null; then DOCKER_VERSION=$($SSH_CMD "docker --version") print_success "Docker 已安装: $DOCKER_VERSION" else print_error "目标设备未安装 Docker" exit 1 fi # 检测 Docker Compose if $SSH_CMD "command -v docker-compose" &> /dev/null; then COMPOSE_VERSION=$($SSH_CMD "docker-compose --version") print_success "Docker Compose 已安装: $COMPOSE_VERSION" else print_error "目标设备未安装 Docker Compose" exit 1 fi } # 检测远程硬件 detect_remote_hardware() { print_info "检测远程硬件配置..." # 检测内存 (GB) TOTAL_MEM=$($SSH_CMD "free -g | awk '/^Mem:/{print \$2}'") print_info "总内存: ${TOTAL_MEM}GB" # 检测 CPU 核心数 CPU_CORES=$($SSH_CMD "nproc") print_info "CPU 核心数: ${CPU_CORES}" # 检测磁盘空间 (GB) DISK_AVAIL=$($SSH_CMD "df -BG / | awk 'NR==2 {print \$4}' | sed 's/G//'") print_info "可用磁盘空间: ${DISK_AVAIL}GB" # 推荐部署模式 if [ "$DEPLOYMENT_MODE" = "auto" ]; then if [ "$TOTAL_MEM" -lt 4 ]; then print_error "内存不足 4GB,无法部署系统" exit 1 elif [ "$TOTAL_MEM" -lt 8 ]; then DEPLOYMENT_MODE="lightweight" print_warning "内存为 ${TOTAL_MEM}GB,将使用轻量级模式" else DEPLOYMENT_MODE="standard" print_success "内存充足,将使用标准模式" fi fi if [ "$DISK_AVAIL" -lt 50 ]; then print_warning "磁盘可用空间不足 50GB,建议清理磁盘" fi } # 生成配置文件 generate_remote_config() { print_info "生成配置文件..." # 创建临时目录 TEMP_DIR=$(mktemp -d) # 复制模板 cp .env.example "$TEMP_DIR/.env" # 生成随机密码 ADMIN_PASSWORD=$(openssl rand -base64 16 | tr -d "=+/" | cut -c1-16) DB_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-32) MINIO_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-32) # 更新配置 sed -i "s/DEPLOYMENT_MODE=.*/DEPLOYMENT_MODE=${DEPLOYMENT_MODE}/" "$TEMP_DIR/.env" sed -i "s/ADMIN_PASSWORD=.*/ADMIN_PASSWORD=${ADMIN_PASSWORD}/" "$TEMP_DIR/.env" sed -i "s/DB_PASSWORD=.*/DB_PASSWORD=${DB_PASSWORD}/" "$TEMP_DIR/.env" sed -i "s/MINIO_PASSWORD=.*/MINIO_PASSWORD=${MINIO_PASSWORD}/" "$TEMP_DIR/.env" print_success "配置文件已生成" # 保存密码供后续使用 echo "$ADMIN_PASSWORD" > "$TEMP_DIR/admin_password.txt" } # 上传文件到远程设备 upload_files() { print_info "上传配置文件到远程设备..." # 创建远程目录 $SSH_CMD "mkdir -p ~/furniture-3d-system" # 构建 SCP 命令 SCP_CMD="scp -P $SSH_PORT" if [ -n "$SSH_KEY" ]; then SCP_CMD="$SCP_CMD -i $SSH_KEY" fi # 上传 .env 文件 $SCP_CMD "$TEMP_DIR/.env" "$USERNAME@$TARGET_HOST:~/furniture-3d-system/" # 上传 docker-compose 文件 COMPOSE_FILE="docker-compose.${DEPLOYMENT_MODE}.yml" $SCP_CMD "$COMPOSE_FILE" "$USERNAME@$TARGET_HOST:~/furniture-3d-system/" print_success "文件上传完成" } # 远程启动服务 start_remote_services() { print_info "在远程设备上启动服务..." COMPOSE_FILE="docker-compose.${DEPLOYMENT_MODE}.yml" # 拉取镜像 print_info "拉取 Docker 镜像..." $SSH_CMD "cd ~/furniture-3d-system && docker-compose -f $COMPOSE_FILE pull" # 启动服务 print_info "启动服务..." $SSH_CMD "cd ~/furniture-3d-system && docker-compose -f $COMPOSE_FILE up -d" print_success "服务已启动" } # 等待服务就绪 wait_for_remote_services() { print_info "等待服务就绪..." MAX_WAIT=120 ELAPSED=0 while [ $ELAPSED -lt $MAX_WAIT ]; do if $SSH_CMD "cd ~/furniture-3d-system && docker-compose ps | grep -q 'healthy'"; then print_success "服务已就绪" return 0 fi sleep 5 ELAPSED=$((ELAPSED + 5)) echo -n "." done echo "" print_warning "服务启动超时,请检查日志" } # 显示访问信息 show_access_info() { ADMIN_PASSWORD=$(cat "$TEMP_DIR/admin_password.txt") echo "" echo "==========================================" echo " 远程部署完成!" echo "==========================================" echo "" print_success "访问地址: http://${TARGET_HOST}:3000" print_success "管理员账号: admin" print_success "管理员密码: $ADMIN_PASSWORD" echo "" print_warning "请妥善保存以上密码!" echo "" print_info "查看日志: ssh $USERNAME@$TARGET_HOST 'cd ~/furniture-3d-system && docker-compose logs -f'" print_info "停止服务: ssh $USERNAME@$TARGET_HOST 'cd ~/furniture-3d-system && docker-compose down'" echo "" # 清理临时文件 rm -rf "$TEMP_DIR" } # 主函数 main() { print_welcome parse_arguments "$@" build_ssh_command test_ssh_connection detect_remote_system detect_remote_hardware generate_remote_config upload_files start_remote_services wait_for_remote_services show_access_info } # 运行主函数 main "$@"