看到你的前端错误日志,问题很清晰了:前端无法连接到后端API。错误 net:ERR_CONNECTION REFUSED 表明前端在尝试调用 http://192.168.8.130/imzs/admin/xxx 时连接被拒绝。

问题分析

  1. API路径错误:前端调用的是 /imzs/admin/...,但你的后端运行在 8081 端口且没有 /imzs 上下文
  2. 后端可能未启动ERR_CONNECTION REFUSED 表示连接被拒绝,说明后端服务没有正常运行
  3. Docker MySQL连接问题:你的脚本中用的是 localhost:3306,但MySQL在Docker容器中

完整的修复版 Jenkins Shell 脚本

#!/bin/bash
set +e

# ==================== 1. 定义全局变量 ====================
WORKSPACE_ROOT="${WORKSPACE}"
FRONTEND_DIR="ivos-web"
BACKEND_DIR="ivos"
NGINX_WEB_DIR="/usr/share/nginx/html/ivos-web"
BACKEND_DEPLOY_DIR="/opt/ivos"
BACKEND_PORT="8081"
DEPLOY_LOG="${BACKEND_DEPLOY_DIR}/deploy.log"
APP_LOG="${BACKEND_DEPLOY_DIR}/app.log"

# ==================== 通用函数 ====================
error_exit() {
    echo "❌ $1"
    echo "=== 最后50行部署日志 ==="
    tail -50 "${DEPLOY_LOG}" 2>/dev/null || echo "无部署日志文件"
    echo "=== 最后50行应用日志 ==="
    tail -50 "${APP_LOG}" 2>/dev/null || echo "无应用日志文件"
    exit 1
}

# ==================== 2. 前置清理 ====================
echo -e "\n===== [0/5] 前置清理 ====="
sudo mkdir -p "${NGINX_WEB_DIR}" "${BACKEND_DEPLOY_DIR}"
sudo mkdir -p ${BACKEND_DEPLOY_DIR}/logs ${BACKEND_DEPLOY_DIR}/files
sudo chmod -R 777 "${NGINX_WEB_DIR}" "${BACKEND_DEPLOY_DIR}"
echo "重新部署时间:$(date)" > "${DEPLOY_LOG}"
echo "应用启动时间:$(date)" > "${APP_LOG}"
echo "✅ 部署环境清理完成"

# ==================== 3. 前端构建 ====================
echo -e "\n===== [1/5] 开始构建前端 ====="
cd "${WORKSPACE_ROOT}/${FRONTEND_DIR}" || error_exit "前端目录不存在!"

# 切换到正确的分支
git checkout myself || echo "切换到myself分支" >> "${DEPLOY_LOG}"
git pull origin myself || echo "拉取最新代码" >> "${DEPLOY_LOG}"

# 检查并修改前端API配置
echo "检查前端API配置..." >> "${DEPLOY_LOG}"
if [ -f ".env.production" ]; then
    # 修改生产环境API地址
    sed -i 's|VUE_APP_API_URL=.*|VUE_APP_API_URL=http://192.168.8.130:8081|g' .env.production
    echo "✅ 更新生产环境API配置" >> "${DEPLOY_LOG}"
elif [ -f ".env" ]; then
    sed -i 's|VUE_APP_API_URL=.*|VUE_APP_API_URL=http://192.168.8.130:8081|g' .env
    echo "✅ 更新环境API配置" >> "${DEPLOY_LOG}"
fi

# 检查vue.config.js或vite.config.js
if [ -f "vue.config.js" ]; then
    # 确保有正确的代理配置
    if ! grep -q "target: 'http://192.168.8.130:8081'" vue.config.js; then
        echo "⚠️ 请检查vue.config.js中的代理配置" >> "${DEPLOY_LOG}"
    fi
fi

# 构建前端
rm -rf node_modules package-lock.json dist
npm install --registry=https://registry.npmmirror.com --force || error_exit "前端依赖安装失败!"
npm run build || error_exit "前端构建失败!"
echo "✅ 前端构建完成"

# ==================== 4. 后端构建 ====================
echo -e "\n===== [2/5] 开始构建后端 ====="
cd "${WORKSPACE_ROOT}/${BACKEND_DIR}" || error_exit "后端目录不存在!"

# 切换到正确的分支
git checkout myself || echo "切换到myself分支" >> "${DEPLOY_LOG}"
git pull origin myself || echo "拉取最新代码" >> "${DEPLOY_LOG}"

# 打包
/usr/local/apache-maven-3.9.8/bin/mvn clean package -DskipTests -U || error_exit "后端打包失败!"
BACKEND_JAR=$(find target -name "*.jar" ! -name "*-sources.jar" ! -name "*-tests.jar" | head -1)
[ -z "${BACKEND_JAR}" ] && error_exit "未找到后端 Jar 包!"
echo "✅ 后端构建完成:${BACKEND_JAR}"

# ==================== 5. 部署前端 ====================
echo -e "\n===== [3/5] 部署前端 ====="
sudo rm -rf "${NGINX_WEB_DIR}"/*
sudo cp -r "${WORKSPACE_ROOT}/${FRONTEND_DIR}/dist/"* "${NGINX_WEB_DIR}/" || error_exit "前端文件复制失败!"

# 配置Nginx反向代理
NGINX_CONF="/etc/nginx/conf.d/ivos.conf"
sudo tee ${NGINX_CONF} > /dev/null << 'EOF'
server {
    listen 80;
    server_name 192.168.8.130;

    # 前端静态文件
    location /ivos-web {
        alias /usr/share/nginx/html/ivos-web;
        try_files $uri $uri/ /ivos-web/index.html;
        index index.html;
    }

    # API代理 - 将 /imzs 代理到后端
    location /imzs {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # 解决前端调用 /imzs/admin 的问题
        proxy_set_header X-Forwarded-Prefix /imzs;
    }

    # 根路径重定向
    location / {
        return 302 /ivos-web/;
    }
}
EOF

# 测试Nginx配置
sudo nginx -t || error_exit "Nginx配置错误"
sudo systemctl reload nginx || sudo systemctl restart nginx
echo "✅ 前端部署完成,Nginx已配置反向代理"

# ==================== 6. 部署后端 ====================
echo -e "\n===== [4/5] 部署后端 ====="

# 停止旧服务
echo "停止旧服务..." >> "${DEPLOY_LOG}"
pkill -f "ivos.jar" 2>/dev/null
# 强制杀死占用端口的进程
OLD_PID=$(lsof -t -i:${BACKEND_PORT} 2>/dev/null)
if [ -n "${OLD_PID}" ]; then
    sudo kill -9 ${OLD_PID} 2>/dev/null
    echo "强制终止进程 PID: ${OLD_PID}" >> "${DEPLOY_LOG}"
fi
sleep 3

# 复制新 Jar
sudo cp "${WORKSPACE_ROOT}/${BACKEND_DIR}/${BACKEND_JAR}" "${BACKEND_DEPLOY_DIR}/ivos.jar" || error_exit "Jar 包复制失败!"
sudo chmod +x "${BACKEND_DEPLOY_DIR}/ivos.jar"

# ==================== 6.1 配置 Java ====================
# 使用 JDK8
if [ -x "/usr/local/jdk8/bin/java" ]; then
    JAVA_CMD="/usr/local/jdk8/bin/java"
elif [ -x "/usr/bin/java" ]; then
    JAVA_CMD="/usr/bin/java"
else
    JAVA_CMD=$(which java 2>/dev/null)
    [ -z "${JAVA_CMD}" ] && error_exit "未找到 Java 环境!"
fi

echo "使用 Java: ${JAVA_CMD}" >> "${DEPLOY_LOG}"
${JAVA_CMD} -version >> "${DEPLOY_LOG}" 2>&1

# ==================== 6.2 获取Docker MySQL连接信息 ====================
echo "配置Docker MySQL连接..." >> "${DEPLOY_LOG}"

# 查找MySQL容器
MYSQL_CONTAINER=$(docker ps --filter "name=mysql" --format "{{.Names}}" | head -1)
if [ -z "$MYSQL_CONTAINER" ]; then
    MYSQL_CONTAINER=$(docker ps --filter "name=mysql-ivos" --format "{{.Names}}" | head -1)
fi

# Docker网关IP
DOCKER_GATEWAY="172.17.0.1"
DB_HOST="${DOCKER_GATEWAY}"

if [ -n "$MYSQL_CONTAINER" ]; then
    echo "✅ 找到MySQL容器: ${MYSQL_CONTAINER}" >> "${DEPLOY_LOG}"
    
    # 测试容器内MySQL
    if docker exec ${MYSQL_CONTAINER} mysql -uroot -proot -e "SELECT 1" &>/dev/null; then
        echo "✅ 容器内MySQL连接成功" >> "${DEPLOY_LOG}"
        
        # 创建数据库
        docker exec ${MYSQL_CONTAINER} mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS ivos;" >> "${DEPLOY_LOG}" 2>&1
        echo "✅ 数据库初始化完成" >> "${DEPLOY_LOG}"
        
        # 显示数据库列表
        docker exec ${MYSQL_CONTAINER} mysql -uroot -proot -e "SHOW DATABASES;" >> "${DEPLOY_LOG}" 2>&1
    else
        echo "⚠️ 容器内MySQL连接失败,尝试修复权限..." >> "${DEPLOY_LOG}"
        # 修复权限
        docker exec ${MYSQL_CONTAINER} mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';" 2>/dev/null
        docker exec ${MYSQL_CONTAINER} mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "FLUSH PRIVILEGES;" 2>/dev/null
    fi
fi

# ==================== 6.3 创建配置文件 ====================
CONFIG_FILE="${BACKEND_DEPLOY_DIR}/application.properties"

# 创建配置文件(使用Docker网关IP)
cat > "${CONFIG_FILE}" << EOF
# 应用服务 WEB 访问端口
server.port=${BACKEND_PORT}
server.servlet.context-path=/

# 数据库连接信息 - 使用Docker网关
spring.datasource.url=jdbc:mysql://${DB_HOST}:3306/ivos?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.maximum-pool-size=10

# MyBatis配置
mybatis.mapper-locations=classpath:mappers/*.xml
mybatis.type-aliases-package=cn.tedu.ivos.entity
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# 日志配置
logging.level.root=WARN
logging.level.cn.tedu.ivos=DEBUG
logging.level.org.mybatis=DEBUG
logging.file.path=${BACKEND_DEPLOY_DIR}/logs

# 文件上传配置
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=500MB

# 静态资源配置
spring.web.resources.static-locations=file:${BACKEND_DEPLOY_DIR}/files,classpath:static

# 允许循环依赖(如果项目中有)
spring.main.allow-circular-references=true
EOF

echo "✅ 配置文件已创建: ${CONFIG_FILE}" >> "${DEPLOY_LOG}"
echo "使用数据库主机: ${DB_HOST}" >> "${DEPLOY_LOG}"

# 创建文件上传目录
sudo mkdir -p /opt/ivos/files
sudo chmod -R 777 /opt/ivos/files

# ==================== 6.4 启动服务 ====================
echo "启动后端服务..." >> "${DEPLOY_LOG}"
cd "${BACKEND_DEPLOY_DIR}" || error_exit "无法进入部署目录"

# 清空旧日志
> "${APP_LOG}"

# 使用配置文件启动
nohup ${JAVA_CMD} -Xms256m -Xmx512m \
  -jar ${BACKEND_DEPLOY_DIR}/ivos.jar \
  --spring.config.location=file:${CONFIG_FILE} \
  >> "${APP_LOG}" 2>&1 &

# 记录PID
echo $! > "${BACKEND_DEPLOY_DIR}/app.pid"
echo "启动PID: $!" >> "${DEPLOY_LOG}"

echo "等待服务启动(30秒)..." >> "${DEPLOY_LOG}"

# 检查启动状态
sleep 5
START_SUCCESS=false
for i in {1..30}; do
    if lsof -i:${BACKEND_PORT} >/dev/null 2>&1; then
        echo "✅ 端口 ${BACKEND_PORT} 已监听" >> "${DEPLOY_LOG}"
        START_SUCCESS=true
        break
    fi
    echo "等待中... ($i/30)" >> "${DEPLOY_LOG}"
    sleep 1
done

# 验证启动
NEW_PID=$(lsof -t -i:${BACKEND_PORT} 2>/dev/null)
if [ -n "${NEW_PID}" ] || [ "$START_SUCCESS" = true ]; then
    echo "✅ 后端服务启动成功,进程ID: ${NEW_PID}" | tee -a "${DEPLOY_LOG}"
    echo "=== 应用启动日志(最后30行)==="
    tail -30 "${APP_LOG}"
    
    # 等待应用完全初始化
    sleep 10
    
    # 测试后端API
    echo "测试后端API..." >> "${DEPLOY_LOG}"
    
    # 测试健康检查
    if curl -s http://localhost:${BACKEND_PORT}/actuator/health >/dev/null 2>&1; then
        HEALTH=$(curl -s http://localhost:${BACKEND_PORT}/actuator/health)
        echo "✅ 健康检查: ${HEALTH}" >> "${DEPLOY_LOG}"
    fi
    
    # 测试API是否可访问(通过Nginx代理路径)
    if curl -s http://localhost/imzs/admin >/dev/null 2>&1; then
        echo "✅ Nginx代理(/imzs)可访问" >> "${DEPLOY_LOG}"
    else
        # 测试直接访问
        if curl -s http://localhost:${BACKEND_PORT} >/dev/null 2>&1; then
            echo "✅ 后端直接访问正常" >> "${DEPLOY_LOG}"
        else
            echo "⚠️ 后端API暂时无法访问" >> "${DEPLOY_LOG}"
        fi
    fi
else
    echo "❌ 后端服务启动失败!" | tee -a "${DEPLOY_LOG}"
    echo "=== 完整应用日志 ==="
    cat "${APP_LOG}"
    
    # 错误诊断
    echo "=== 错误诊断 ===" | tee -a "${DEPLOY_LOG}"
    
    # 检查数据库错误
    if grep -i "database\|mysql\|connection" "${APP_LOG}" | grep -i "error\|refused\|timeout" >/dev/null; then
        echo "⚠️ 检测到数据库连接错误,请检查:" | tee -a "${DEPLOY_LOG}"
        echo "   1. MySQL容器状态:docker ps | grep mysql" | tee -a "${DEPLOY_LOG}"
        echo "   2. 从宿主机连接测试:mysql -h${DB_HOST} -P3306 -uroot -proot" | tee -a "${DEPLOY_LOG}"
        echo "   3. 容器内MySQL状态:docker exec -it ${MYSQL_CONTAINER} mysql -uroot -proot -e 'SHOW DATABASES;'" | tee -a "${DEPLOY_LOG}"
    fi
    
    # 检查端口冲突
    if grep -i "address already in use\|port" "${APP_LOG}" >/dev/null; then
        echo "⚠️ 检测到端口冲突:" | tee -a "${DEPLOY_LOG}"
        echo "   端口 ${BACKEND_PORT} 被以下进程占用:" | tee -a "${DEPLOY_LOG}"
        lsof -i:${BACKEND_PORT} | tee -a "${DEPLOY_LOG}"
    fi
    
    exit 1
fi

# ==================== 7. 最终验证 ====================
echo -e "\n===== [5/5] 最终验证 ====="

# 验证前端访问
echo "验证前端访问..." >> "${DEPLOY_LOG}"
FRONTEND_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/ivos-web)
if [ "${FRONTEND_CODE}" = "200" ] || [ "${FRONTEND_CODE}" = "302" ]; then
    echo "✅ 前端访问正常 (HTTP ${FRONTEND_CODE})" >> "${DEPLOY_LOG}"
else
    echo "⚠️ 前端访问返回 HTTP ${FRONTEND_CODE}" >> "${DEPLOY_LOG}"
fi

# 验证API代理
echo "验证API代理..." >> "${DEPLOY_LOG}"
API_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/imzs/admin 2>/dev/null || echo "000")
if [ "${API_CODE}" != "000" ] && [ "${API_CODE}" != "404" ]; then
    echo "✅ API代理正常 (HTTP ${API_CODE})" >> "${DEPLOY_LOG}"
else
    echo "⚠️ API代理可能有问题 (HTTP ${API_CODE})" >> "${DEPLOY_LOG}"
    echo "   请检查后端服务是否完全启动" >> "${DEPLOY_LOG}"
fi

# 显示Docker容器状态
echo "=== Docker容器状态 ===" >> "${DEPLOY_LOG}"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -i mysql >> "${DEPLOY_LOG}" 2>&1 || echo "无MySQL容器" >> "${DEPLOY_LOG}"

# ==================== 8. 部署完成 ====================
echo -e "\n🎉===== 部署完成!====="
IP_ADDR="192.168.8.130"
echo "👉 前端访问地址:http://${IP_ADDR}/ivos-web"
echo "👉 后端接口地址(直接):http://${IP_ADDR}:${BACKEND_PORT}"
echo "👉 后端接口地址(代理):http://${IP_ADDR}/imzs"
echo "👉 API测试:curl http://${IP_ADDR}/imzs/admin"
echo "👉 数据库连接:${DB_HOST}:3306 (Docker容器: ${MYSQL_CONTAINER:-未找到})"
echo "👉 查看日志:tail -f ${APP_LOG}"
echo "👉 配置文件:${CONFIG_FILE}"

# 显示简要状态
echo -e "\n📊 运行状态:"
echo "   后端进程PID: $(cat ${BACKEND_DEPLOY_DIR}/app.pid 2>/dev/null || echo '未知')"
echo "   MySQL容器: ${MYSQL_CONTAINER:-未找到}"
echo "   Nginx状态: $(systemctl is-active nginx)"

exit 0

关键修改点

  1. Nginx反向代理配置:将 /imzs 路径代理到后端 8081 端口
  2. Docker MySQL连接:使用 172.17.0.1 网关IP而不是 localhost
  3. 前端API配置:自动修改前端环境变量
  4. 完整的错误诊断:提供详细的错误信息

部署后验证

# 1. 检查后端是否运行
curl http://192.168.8.130:8081

# 2. 检查Nginx代理
curl http://192.168.8.130/imzs/admin

# 3. 查看应用日志
tail -f /opt/ivos/app.log

# 4. 检查MySQL连接
docker exec -it mysql-ivos mysql -uroot -proot -e "SHOW DATABASES;"

这样修改后,前端应该能正常通过 /imzs 路径调用后端API了。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐