diff --git a/Jenkinsfile b/Jenkinsfile index 2e02b13..f6d1976 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,8 +6,12 @@ pipeline { } environment { - // 抽取部署目标路径为公共变量 - DEPLOY_DIR = '/data/nginx/www/fafamall/demo' + DEPLOY_DIR = '/data/nginx/www/fafamall/demo' // 主节点部署目录 + SLAVE_IP = '172.16.0.10' // 从节点 IP + SLAVE_DEPLOY_DIR = '/data/nginx/www/fafamall/demo' // 从节点目标目录(与主节点一致) + SSH_PORT = '2203' // 从节点 SSH 端口 + SSH_KEY = '/root/.ssh/id_rsa' // Jenkins 服务器(主节点)免密私钥路径 + DIST_PATH = 'dist' // 编译产物目录(与 npm run build 输出目录一致) } stages { @@ -20,15 +24,15 @@ pipeline { stage('安装依赖') { steps { sh ''' - echo "清理旧依赖..." - rm -rf node_modules package-lock.json - npm cache clean --force + echo "清理旧依赖..." + rm -rf node_modules package-lock.json + npm cache clean --force - echo "设置国内镜像源加速..." - npm config set registry https://registry.npmmirror.com - - # 安装其他依赖 - npm install + echo "设置国内镜像源加速..." + npm config set registry https://registry.npmmirror.com + + # 安装其他依赖 + npm install ''' } } @@ -36,27 +40,82 @@ pipeline { stage('构建项目') { steps { sh 'npm run build' + // 验证构建产物是否存在(避免空同步) + sh """ + [ -d "${DIST_PATH}" ] || { echo "错误:构建失败,未找到 ${DIST_PATH} 目录"; exit 1; } + echo "构建成功:${DIST_PATH} 目录存在" + """ } } - stage('部署项目') { + stage('主节点部署') { steps { sh ''' # 公共部署逻辑(创建目录、清理、复制) mkdir -p ${DEPLOY_DIR} rm -rf ${DEPLOY_DIR}/* - cp -r dist/* ${DEPLOY_DIR}/ + cp -r ${DIST_PATH}/* ${DEPLOY_DIR}/ + echo "主节点部署完成:${DIST_PATH} → ${DEPLOY_DIR}" ''' } } + + stage('同步到从节点') { + steps { + sh """ + # 核心逻辑:1. 远程创建从节点目录 2. rsync 同步文件(保持主从一致) + echo "========================================" + echo "开始同步主节点 → 从节点" + echo "主节点目录:${DEPLOY_DIR}" + echo "从节点信息:${SLAVE_IP}:${SLAVE_DEPLOY_DIR}(SSH端口:${SSH_PORT})" + echo "========================================" + + # 步骤1:远程创建从节点目标目录(-p 递归创建,已存在不报错) + echo "第一步:创建从节点目标目录..." + ssh -i ${SSH_KEY} \ + -p ${SSH_PORT} \ + -o StrictHostKeyChecking=no \ + -o ConnectTimeout=10 \ + root@${SLAVE_IP} \ + "mkdir -p ${SLAVE_DEPLOY_DIR}" + + # 检查目录创建结果 + if [ \$? -ne 0 ]; then + echo "错误:从节点目录创建失败!请检查:" + echo "1. 主节点是否免密登录从节点(私钥路径:${SSH_KEY})" + echo "2. 从节点 SSH 端口 ${SSH_PORT} 是否放行" + echo "3. 从节点 root 权限是否足够" + exit 1 + fi + + # 步骤2:rsync 同步文件(核心同步逻辑) + echo "第二步:开始 rsync 同步文件..." + rsync -avz \ + --delete \ + --exclude="*.log" \ + --exclude="node_modules" \ + -e "ssh -i ${SSH_KEY} -p ${SSH_PORT} -o StrictHostKeyChecking=no" \ + ${DEPLOY_DIR}/ \ + root@${SLAVE_IP}:${SLAVE_DEPLOY_DIR}/ + + # 检查同步结果 + if [ \$? -eq 0 ]; then + echo "✅ 从节点同步成功!主从目录完全一致" + else + echo "❌ 从节点同步失败!请查看 Jenkins 控制台日志详情" + exit 1 + fi + """ + } + } } post { success { - echo '项目部署成功.' + echo '🎉 项目部署+从节点同步全部成功!' } failure { - echo '项目部署失败.' + echo '❌ 项目部署/同步失败,请排查问题后重试!' } } } \ No newline at end of file