#!/bin/bash # 应用打包脚本 - 在开发环境运行 APP_NAME="wuyuanbiaoba-web" # 自动读取 package.json 的 version 字段,如果失败则用 latest 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}.tar.gz" echo "打包 Node.js 应用..." # 清理旧构建 rm -rf $TARGET_DIR mkdir -p $TARGET_DIR # 复制源代码 # 复制文件 cp package.json $TARGET_DIR/ cp package-lock.json $TARGET_DIR/ cp index.html $TARGET_DIR/ cp config.cjs $TARGET_DIR/ [ -f README.md ] && cp README.md $TARGET_DIR/ # 复制目录 cp -r client/ $TARGET_DIR/ cp -r server/ $TARGET_DIR/ cp -r script/ $TARGET_DIR/ # 创建部署脚本 cat > $TARGET_DIR/deploy.sh << 'EOF' #!/bin/bash # 应用部署脚本 APP_NAME="wuyuanbiaoba-web" INSTALL_DIR="/opt/$APP_NAME" SERVICE_NAME="$APP_NAME.service" NODE_VERSION="20.19.3" echo "正在部署 $APP_NAME..." # 检查是否为 root 权限 if [ "$EUID" -ne 0 ]; then echo "错误: 请使用 root 权限运行此脚本 (sudo ./deploy.sh)" exit 1 fi # 检查 systemd 是否可用 if ! pidof systemd &>/dev/null; then echo "错误: 当前系统不支持 systemd" exit 1 fi # 自动安装 Node.js 函数 install_nodejs() { echo "正在自动安装 Node.js $NODE_VERSION..." # 保存当前工作目录 ORIGINAL_DIR=$(pwd) # 检测系统架构 ARCH=$(uname -m) case $ARCH in x86_64) NODE_ARCH="x64" ;; aarch64) NODE_ARCH="arm64" ;; armv7l) NODE_ARCH="armv7l" ;; *) echo "错误: 不支持的系统架构: $ARCH" exit 1 ;; esac NODE_PACKAGE="node-v$NODE_VERSION-linux-$NODE_ARCH" DOWNLOAD_URL="https://nodejs.org/dist/v$NODE_VERSION/$NODE_PACKAGE.tar.xz" # 创建临时目录 cd /tmp # 下载 Node.js echo "下载 Node.js..." if ! wget -q --show-progress "$DOWNLOAD_URL"; then echo "错误: 下载 Node.js 失败,请检查网络连接" cd "$ORIGINAL_DIR" # 失败时也要恢复目录 exit 1 fi # 解压并安装 echo "安装 Node.js..." tar -xJf "$NODE_PACKAGE.tar.xz" mv "$NODE_PACKAGE" "/usr/local/node-v$NODE_VERSION" # 创建软链接 ln -sf "/usr/local/node-v$NODE_VERSION/bin/node" /usr/local/bin/node ln -sf "/usr/local/node-v$NODE_VERSION/bin/npm" /usr/local/bin/npm ln -sf "/usr/local/node-v$NODE_VERSION/bin/npx" /usr/local/bin/npx # 清理下载文件 rm -f "/tmp/$NODE_PACKAGE.tar.xz" # 恢复原工作目录 cd "$ORIGINAL_DIR" # 验证安装 if node -v && npm -v; then echo "Node.js 安装成功!" echo "Node.js 版本: $(node -v)" echo "npm 版本: $(npm -v)" else echo "错误: Node.js 安装失败" exit 1 fi } # 检查 Node.js 是否安装 if ! command -v node &> /dev/null; then echo "未检测到 Node.js,将自动安装..." install_nodejs else # 检查 Node.js 版本 CURRENT_NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) if [ "$CURRENT_NODE_VERSION" -lt 20 ]; then echo "当前 Node.js 版本过低 ($(node -v)),将自动升级到 v$NODE_VERSION..." install_nodejs else echo "检测到 Node.js 版本: $(node -v)" fi fi # 检查 npm 是否可用 if ! command -v npm &> /dev/null; then echo "错误: npm 不可用,请检查 Node.js 安装" exit 1 fi # 停止现有服务 if systemctl is-active --quiet $SERVICE_NAME; then echo "停止现有服务..." systemctl stop $SERVICE_NAME sleep 2 fi # 禁用现有服务 if systemctl is-enabled --quiet $SERVICE_NAME; then echo "禁用现有服务..." systemctl disable $SERVICE_NAME fi # 清理超过7天的旧备份 if [ -d "/opt" ]; then echo "清理超过7天的旧备份..." 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" "README.md" ) REQUIRED_DIRS=( "client" "server" "script" ) # 复制必需文件 for file in "${REQUIRED_FILES[@]}"; do if [ -f "$file" ]; then cp "$file" "$INSTALL_DIR/" echo "已复制: $file" else echo "警告: 缺少文件 $file" fi done # 复制必需目录 for dir in "${REQUIRED_DIRS[@]}"; do if [ -d "$dir" ]; then cp -r "$dir/" "$INSTALL_DIR/" echo "已复制目录: $dir/" else echo "警告: 缺少目录 $dir" fi done # 复制可选配置文件(如果存在) OPTIONAL_FILES=(".env" ".npmrc" ".editorconfig") for file in "${OPTIONAL_FILES[@]}"; do if [ -f "$file" ]; then cp "$file" "$INSTALL_DIR/" echo "已复制配置文件: $file" fi done # 验证关键文件 if [ ! -f "$INSTALL_DIR/package.json" ]; then echo "错误: package.json 复制失败" exit 1 fi echo "文件复制完成,安装目录内容:" ls -la "$INSTALL_DIR/" # 安装依赖 echo "安装依赖包..." cd $INSTALL_DIR npm install # 检查主入口文件 if [ ! -f "package.json" ]; then echo "错误: package.json 文件不存在" exit 1 fi # 获取 npm 和 node 的完整路径 NPM_PATH=$(which npm) NODE_PATH=$(which node) echo "使用 Node.js: $NODE_PATH" echo "使用 npm: $NPM_PATH" # 设置 systemd 环境变量 SYSTEMD_PATH="/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin" EXEC_START="$NPM_PATH start" # 创建 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=$EXEC_START Restart=on-failure RestartSec=10 Environment=NODE_ENV=development Environment=PATH=$SYSTEMD_PATH [Install] WantedBy=multi-user.target SERVICE_EOF # 重新加载 systemd systemctl daemon-reload # 启用并启动服务 systemctl enable $SERVICE_NAME systemctl start $SERVICE_NAME # 等待服务启动 sleep 3 echo "部署完成! 服务状态:" systemctl status $SERVICE_NAME --no-pager # 清理部署目录(自动清理) DEPLOY_DIR=$(pwd) if [[ "$DEPLOY_DIR" == "/tmp/"* ]]; then echo "清理部署临时目录: $DEPLOY_DIR" cd /tmp rm -rf "$DEPLOY_DIR" fi echo "" echo "✅ 部署成功!" echo "🔍 查看服务状态: systemctl status $SERVICE_NAME" echo "📋 查看实时日志: journalctl -u $SERVICE_NAME -f" EOF # 创建打包文件 tar -czf $DEPLOY_PACKAGE -C $TARGET_DIR . echo "打包完成: $DEPLOY_PACKAGE" echo "请将此文件上传到服务器并解压后运行 ./deploy.sh"