Jenkins Shell 脚本
错误表明前端在尝试调用时连接被拒绝。
·
看到你的前端错误日志,问题很清晰了:前端无法连接到后端API。错误 net:ERR_CONNECTION REFUSED 表明前端在尝试调用 http://192.168.8.130/imzs/admin/xxx 时连接被拒绝。
问题分析
- API路径错误:前端调用的是
/imzs/admin/...,但你的后端运行在8081端口且没有/imzs上下文 - 后端可能未启动:
ERR_CONNECTION REFUSED表示连接被拒绝,说明后端服务没有正常运行 - 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
关键修改点
- Nginx反向代理配置:将
/imzs路径代理到后端8081端口 - Docker MySQL连接:使用
172.17.0.1网关IP而不是localhost - 前端API配置:自动修改前端环境变量
- 完整的错误诊断:提供详细的错误信息
部署后验证
# 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了。
更多推荐
所有评论(0)