diff --git a/README.md b/README.md index 405a0d8..d322b4e 100644 --- a/README.md +++ b/README.md @@ -12,23 +12,12 @@ ### 部署步骤 **特别注意** -确保下位机已经安装了 nodejs 环境,并且版本在 20 以上,注意,nodejs 环境必须是 root 用户可用的,因为服务自启动需要 root 权限。 +确保下位机已经安装了 nodejs 环境,并且版本在 20 以上(推荐v20.19.3),注意,nodejs 环境必须是 root 用户可用的,服务自启动需要 systemd 的操作权限。 -#### nodejs 安装指南 -```shell -sudo su - -# 安装 nvm -export NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node -export NVM_INSTALL_GITHUB_REPO="https://ghproxy.com/https://github.com/nvm-sh/nvm" -curl -o- https://ghproxy.com/https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash -source ~/.bashrc -nvm install 20 -nvm use 20 -``` 1. 从项目的 [release](https://gitea.anxinyun.cn/qinjian/wuyuanbiaoba_web/releases) 页面下载最新的打包文件,如 `wuyuanbiaoba-web-x.x.x.tar.gz` -2. 上传到服务器的临时目录,如 `/tmp/folder/`(这里最好建立一个新的目录存放压缩文件) +2. 上传到服务器的临时目录,如 `~/deploy/`(这里最好建立一个新的目录存放压缩文件) 3. 进入该目录,解压文件 `tar -xzf wuyuanbiaoba-web-x.x.x.tar.gz` 4. 进入解压后的目录 `cd wuyuanbiaoba-web-x.x.x` 5. 运行部署脚本 `sudo ./deploy.sh` diff --git a/script/package-app.sh b/script/package-app.sh index d00822f..e1e7f52 100644 --- a/script/package-app.sh +++ b/script/package-app.sh @@ -38,6 +38,7 @@ cat > $TARGET_DIR/deploy.sh << 'EOF' APP_NAME="wuyuanbiaoba-web" INSTALL_DIR="/opt/$APP_NAME" SERVICE_NAME="$APP_NAME.service" +NODE_VERSION="20.19.3" echo "正在部署 $APP_NAME..." @@ -53,22 +54,83 @@ if ! pidof systemd &>/dev/null; then exit 1 fi +# 自动安装 Node.js 函数 +install_nodejs() { + echo "正在自动安装 Node.js $NODE_VERSION..." + + # 检测系统架构 + 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 失败,请检查网络连接" + 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" + + # 验证安装 + 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 未安装。请为 root 用户安装 Node.js 20+" - exit 1 -fi - -# 检查 Node.js 版本 -NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) -if [ "$NODE_VERSION" -lt 20 ]; then - echo "错误: Node.js 版本过低 (当前: $(node -v)),需要 20+" - exit 1 + 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 未安装或不可用" + echo "错误: npm 不可用,请检查 Node.js 安装" exit 1 fi @@ -85,6 +147,12 @@ if systemctl is-enabled --quiet $SERVICE_NAME; then 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)" @@ -95,18 +163,61 @@ fi # 创建安装目录 mkdir -p $INSTALL_DIR -# 复制文件 +# 复制应用文件 echo "复制应用文件..." -cp -r ./* $INSTALL_DIR/ -# 复制隐藏文件(如果存在) -shopt -s dotglob -for file in .*; do - if [[ "$file" != "." && "$file" != ".." ]]; then - cp -r "$file" "$INSTALL_DIR/" 2>/dev/null || true +# 创建文件清单,确保只复制打包时包含的文件 +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 -shopt -u dotglob + +# 复制可选配置文件(如果存在) +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 "安装依赖包..." @@ -126,20 +237,9 @@ NODE_PATH=$(which node) echo "使用 Node.js: $NODE_PATH" echo "使用 npm: $NPM_PATH" -# 检查是否使用 nvm 并设置环境变量 -if [[ "$NODE_PATH" == *"/.nvm/"* ]]; then - echo "检测到使用 nvm 管理 Node.js" - NVM_NODE_DIR=$(dirname "$NODE_PATH") - echo "Node.js 目录: $NVM_NODE_DIR" - # 为 systemd 设置完整的 PATH - SYSTEMD_PATH="$NVM_NODE_DIR:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - # 使用 node 直接执行 npm,避免 env 查找问题 - EXEC_START="$NODE_PATH $NPM_PATH start" -else - echo "使用系统安装的 Node.js" - SYSTEMD_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - EXEC_START="$NPM_PATH start" -fi +# 设置 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 @@ -168,36 +268,24 @@ systemctl daemon-reload systemctl enable $SERVICE_NAME systemctl start $SERVICE_NAME +# 等待服务启动 +sleep 3 + echo "部署完成! 服务状态:" systemctl status $SERVICE_NAME --no-pager -EOF - -chmod +x $TARGET_DIR/deploy.sh -# 创建安装说明 -cat > $TARGET_DIR/README.md << 'EOF' -# 应用安装说明 - -## 要求 -- Linux 系统 -- Node.js 20+ 已安装 - -## 安装步骤 -1. 上传此文件夹到目标服务器 -2. 运行: ./deploy.sh - -## 管理服务 -- 启动: sudo systemctl start wuyuanbiaoba-web.service -- 停止: sudo systemctl stop wuyuanbiaoba-web.service -- 状态检查: sudo systemctl status wuyuanbiaoba-web.service -- 查看日志: journalctl -u wuyuanbiaoba-web.service -f +# 清理部署目录(自动清理) +DEPLOY_DIR=$(pwd) +if [[ "$DEPLOY_DIR" == "/tmp/"* ]]; then + echo "清理部署临时目录: $DEPLOY_DIR" + cd /tmp + rm -rf "$DEPLOY_DIR" +fi -# 完全卸载 -sudo systemctl stop wuyuanbiaoba-web.service -sudo systemctl disable wuyuanbiaoba-web.service -sudo rm /etc/systemd/system/wuyuanbiaoba-web.service -sudo systemctl daemon-reload -sudo rm -rf /opt/wuyuanbiaoba-web* +echo "" +echo "✅ 部署成功!" +echo "🔍 查看服务状态: systemctl status $SERVICE_NAME" +echo "📋 查看实时日志: journalctl -u $SERVICE_NAME -f" EOF # 创建打包文件