#!/bin/bash # Linux 离线打包脚本 - 开发模式部署 APP_NAME="wuyuanbiaoba-web" # 读取版本号 if [ -f package.json ]; then VERSION=$(grep '"version"' package.json | head -1 | sed -E 's/.*"version": *"([^"]+)".*/\1/') [ -z "$VERSION" ] && VERSION="latest" else VERSION="latest" fi TARGET_DIR="./build" DEPLOY_PACKAGE="${APP_NAME}-${VERSION}-offline.tar.gz" echo "================================================" echo "🚀 Linux 离线打包" echo "================================================" echo "应用: $APP_NAME" echo "版本: $VERSION" echo "" # 检查必要工具 check_command() { if ! command -v $1 &> /dev/null; then echo "❌ 错误: 未找到 $1 命令" exit 1 fi } check_command "node" check_command "npm" check_command "tar" echo "✅ 环境检查通过" echo " Node.js: $(node -v)" echo " npm: $(npm -v)" echo "" # 清理旧构建 echo "🧹 清理旧构建..." rm -rf $TARGET_DIR rm -f *.tar.gz mkdir -p $TARGET_DIR # 复制源代码 echo "" echo "📁 复制源代码..." REQUIRED_FILES=( "package.json" "package-lock.json" "index.html" "config.cjs" ) REQUIRED_DIRS=( "client" "server" "script" ) # 复制文件 for file in "${REQUIRED_FILES[@]}"; do if [ -f "$file" ]; then cp "$file" "$TARGET_DIR/" echo " ✅ $file" else echo " ⚠️ 警告: 缺少 $file" fi done # 复制目录 for dir in "${REQUIRED_DIRS[@]}"; do if [ -d "$dir" ]; then cp -r "$dir" "$TARGET_DIR/" echo " ✅ $dir/" else echo " ⚠️ 警告: 缺少 $dir/" fi done # 复制 README(可选) [ -f README.md ] && cp README.md "$TARGET_DIR/" && echo " ✅ README.md" # 安装依赖(包括 devDependencies,因为开发模式需要) echo "" echo "📦 安装依赖 (包括开发依赖)..." echo " 这可能需要几分钟..." echo "" cd $TARGET_DIR # 使用 npm install 安装所有依赖(不是 --production) echo "安装依赖..." npm install if [ $? -ne 0 ]; then echo "❌ npm 安装失败" exit 1 fi cd .. echo "" echo "✅ node_modules 安装完成" echo " 大小: $(du -sh $TARGET_DIR/node_modules | cut -f1)" # 创建部署脚本(参照 package-app.sh 的逻辑) echo "" echo "📝 生成部署脚本..." cat > $TARGET_DIR/deploy.sh << 'DEPLOY_EOF' #!/bin/bash # 应用部署脚本(离线版本,开发模式) APP_NAME="wuyuanbiaoba-web" INSTALL_DIR="/opt/$APP_NAME" SERVICE_NAME="$APP_NAME.service" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" echo "================================================" echo "🚀 部署 $APP_NAME (离线开发模式)" echo "================================================" # Root 权限检查 if [ "$EUID" -ne 0 ]; then echo "❌ 错误: 需要 root 权限" echo " 使用: sudo ./deploy.sh" exit 1 fi # systemd 检查 if ! pidof systemd &>/dev/null; then echo "❌ 错误: 系统不支持 systemd" exit 1 fi # 检查 Node.js 环境 echo "" echo "🔍 检查 Node.js 环境..." if ! command -v node &> /dev/null; then echo "❌ 错误: 未安装 Node.js" echo " 请先安装 Node.js 20 或更高版本" exit 1 fi if ! command -v npm &> /dev/null; then echo "❌ 错误: 未安装 npm" exit 1 fi NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) if [ "$NODE_VERSION" -lt 20 ]; then echo "❌ 错误: Node.js 版本过低 ($(node -v))" echo " 需要 Node.js 20 或更高版本" exit 1 fi echo " ✅ Node.js: $(node -v)" echo " ✅ npm: $(npm -v)" # 部署应用 echo "" echo "🛠️ 开始部署..." # 停止服务 if systemctl is-active --quiet $SERVICE_NAME; then echo " 停止服务..." systemctl stop $SERVICE_NAME sleep 2 fi if systemctl is-enabled --quiet $SERVICE_NAME 2>/dev/null; then echo " 禁用服务..." systemctl disable $SERVICE_NAME 2>/dev/null fi # 清理旧备份(保留7天内的) if [ -d "/opt" ]; then echo " 清理旧备份..." find /opt -maxdepth 1 -name "${APP_NAME}_backup_*" -type d -mtime +7 -exec rm -rf {} \; 2>/dev/null || true fi # 备份现有版本 if [ -d "$INSTALL_DIR" ]; then BACKUP_DIR="${INSTALL_DIR}_backup_$(date +%Y%m%d_%H%M%S)" echo " 备份到: $BACKUP_DIR" mv "$INSTALL_DIR" "$BACKUP_DIR" fi # 创建安装目录 mkdir -p $INSTALL_DIR # 复制应用文件 echo " 复制文件..." # 创建文件清单,确保只复制打包时包含的文件 REQUIRED_FILES=( "package.json" "package-lock.json" "index.html" "config.cjs" ) REQUIRED_DIRS=( "client" "server" "script" "node_modules" ) # 复制必需文件 for file in "${REQUIRED_FILES[@]}"; do if [ -f "$SCRIPT_DIR/$file" ]; then cp "$SCRIPT_DIR/$file" "$INSTALL_DIR/" echo " ✅ $file" else echo " ⚠️ 警告: 缺少 $file" fi done # 复制必需目录 for dir in "${REQUIRED_DIRS[@]}"; do if [ -d "$SCRIPT_DIR/$dir" ]; then cp -r "$SCRIPT_DIR/$dir" "$INSTALL_DIR/" echo " ✅ $dir/" else echo " ⚠️ 警告: 缺少 $dir" fi done # 复制可选文件 [ -f "$SCRIPT_DIR/README.md" ] && cp "$SCRIPT_DIR/README.md" "$INSTALL_DIR/" && echo " ✅ README.md" # 验证关键文件 echo "" echo "🔍 验证部署..." MISSING=0 REQUIRED_CHECK=( "package.json" "node_modules" "server" "client" "index.html" "config.cjs" ) for item in "${REQUIRED_CHECK[@]}"; do if [ ! -e "$INSTALL_DIR/$item" ]; then echo " ❌ 缺少: $item" MISSING=1 else echo " ✅ $item" fi done if [ $MISSING -eq 1 ]; then echo "" echo "❌ 部署验证失败" exit 1 fi # 验证关键依赖 if [ ! -d "$INSTALL_DIR/node_modules/@peace/react_client" ]; then echo " ⚠️ 警告: 缺少关键依赖 @peace/react_client" fi # 获取 npm 和 node 的完整路径 NPM_PATH=$(which npm) NODE_PATH=$(which node) echo "" echo "⚙️ 配置服务..." echo " Node: $NODE_PATH" echo " npm: $NPM_PATH" # 设置 systemd 环境变量 SYSTEMD_PATH="/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin" # 创建启动脚本 cat > $INSTALL_DIR/start.sh << STARTEOF #!/bin/bash cd $INSTALL_DIR export NODE_ENV=development export PATH=$SYSTEMD_PATH exec $NPM_PATH start STARTEOF chmod +x $INSTALL_DIR/start.sh # 创建 systemd 服务文件(开发模式) cat > /etc/systemd/system/$SERVICE_NAME << SERVICE_EOF [Unit] Description=$APP_NAME Node.js Application After=network.target [Service] Type=simple User=root WorkingDirectory=$INSTALL_DIR ExecStart=$INSTALL_DIR/start.sh Restart=on-failure RestartSec=10 Environment=NODE_ENV=development Environment=PATH=$SYSTEMD_PATH StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target SERVICE_EOF # 重新加载 systemd systemctl daemon-reload # 启用并启动服务 systemctl enable $SERVICE_NAME systemctl start $SERVICE_NAME # 等待服务启动 sleep 3 echo "" echo "================================================" echo "📊 部署结果" echo "================================================" systemctl status $SERVICE_NAME --no-pager # 清理部署目录(如果在 /tmp 下) DEPLOY_DIR="$SCRIPT_DIR" if [[ "$DEPLOY_DIR" == "/tmp/"* ]]; then echo "" echo "🗑️ 清理部署临时目录: $DEPLOY_DIR" cd /tmp rm -rf "$DEPLOY_DIR" fi echo "" echo "================================================" echo "✅ 部署完成!" echo "================================================" echo "" echo "📌 常用命令:" echo " 状态: systemctl status $SERVICE_NAME" echo " 日志: journalctl -u $SERVICE_NAME -f" echo " 重启: systemctl restart $SERVICE_NAME" echo " 停止: systemctl stop $SERVICE_NAME" echo "" DEPLOY_EOF chmod +x $TARGET_DIR/deploy.sh # 创建打包 echo "" echo "📦 创建离线部署包..." echo "" cd $TARGET_DIR tar -czf ../$DEPLOY_PACKAGE . 2>&1 | grep -v "tar: Removing leading" cd .. if [ ! -f "$DEPLOY_PACKAGE" ]; then echo "❌ 打包失败" exit 1 fi PACKAGE_SIZE=$(du -h $DEPLOY_PACKAGE | cut -f1) echo "" echo "================================================" echo "✅ 打包完成!" echo "================================================" echo "" echo "📦 部署包信息:" echo " 文件名: $DEPLOY_PACKAGE" echo " 大小: $PACKAGE_SIZE" echo " 位置: $(pwd)/$DEPLOY_PACKAGE" echo "" echo "📋 包含内容:" echo " ✅ 应用源代码" echo " ✅ node_modules (包括开发依赖)" echo " ✅ 部署脚本" echo "" echo "🎯 部署要求:" echo " - Node.js >= 20.0.0" echo " - npm" echo " - systemd" echo "" echo "🎯 部署步骤:" echo " 1. 上传到目标服务器" echo " 2. 解压: tar -xzf $DEPLOY_PACKAGE" echo " 3. 部署: sudo ./deploy.sh" echo "" echo "💡 此包以开发模式运行,包含所有依赖" echo ""