如何在生产环境中使用脚本自动化部署

在生产环境中实现 Tomcat 应用的脚本自动化部署,核心是结合「Nginx 流量切分 + Tomcat Manager API + 健康检查 + 回滚机制」,编写可复用、高可靠的 Shell 脚本,实现「一键部署、零停机、失败回滚」。以下是生产级自动化部署脚本的完整实现,包含单节点 / 集群两种场景,可直接复制使用。

核心设计原则(生产环境必备)

  1. 零停机:通过 Nginx 临时下线节点,避免部署期间请求失败;
  2. 原子性:部署前验证、部署中监控、部署失败自动回滚;
  3. 可追溯:详细日志记录部署过程,便于排查问题;
  4. 权限控制:仅允许指定用户执行部署脚本,避免误操作;
  5. 版本管理:保留历史 war 包,支持一键回滚到任意版本。

一、单节点 Tomcat 自动化部署脚本(基础版)

适合单节点 Tomcat 生产环境,实现「热部署 + 健康检查 + 日志记录」。

1. 脚本完整代码(deploy_single.sh)

bash
运行
#!/bin/bash
# 生产环境 Tomcat 单节点自动化部署脚本
# 用法:./deploy_single.sh 应用名 war包路径 TomcatIP Tomcat端口 部署账号 部署密码

# ====================== 配置项(可根据实际修改)======================
APP_NAME=$1          # 应用名(如 myapp)
WAR_PATH=$2          # 本地 war 包路径(如 /data/build/myapp.war)
TOMCAT_IP=$3         # Tomcat 服务器IP(如 192.168.1.100)
TOMCAT_PORT=$4       # Tomcat 端口(如 8080)
DEPLOY_USER=$5       # Tomcat Manager 账号(如 deploy_admin)
DEPLOY_PWD=$6        # Tomcat Manager 密码(如 Deploy@1234)
HEALTH_CHECK_URL="http://${TOMCAT_IP}:${TOMCAT_PORT}/${APP_NAME}/health" # 健康检查接口
LOG_FILE="/var/log/tomcat_deploy_${APP_NAME}.log"                       # 部署日志路径
BACKUP_DIR="/data/tomcat_backup/${APP_NAME}"                             # 历史包备份目录

# ====================== 函数定义 ======================
# 日志打印函数(带时间戳)
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a ${LOG_FILE}
}

# 健康检查函数
health_check() {
    log "开始健康检查:${HEALTH_CHECK_URL}"
    for ((i=1; i<=10; i++)); do
        HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${HEALTH_CHECK_URL})
        if [ "${HTTP_CODE}" == "200" ]; then
            log "应用健康检查通过!HTTP状态码:${HTTP_CODE}"
            return 0
        fi
        log "健康检查第${i}次失败,HTTP状态码:${HTTP_CODE},5秒后重试..."
        sleep 5
    done
    log "应用健康检查失败!请检查应用状态"
    return 1
}

# 回滚函数
rollback() {
    log "开始回滚到上一版本..."
    # 查找最新的备份包
    LAST_WAR=$(ls -t ${BACKUP_DIR}/${APP_NAME}_*.war | head -1)
    if [ -z "${LAST_WAR}" ]; then
        log "无历史备份包,回滚失败!"
        exit 1
    fi
    # 重新部署备份包
    curl -u ${DEPLOY_USER}:${DEPLOY_PWD} -T ${LAST_WAR} "http://${TOMCAT_IP}:${TOMCAT_PORT}/manager/text/deploy?path=/${APP_NAME}&update=true"
    if [ $? -eq 0 ]; then
        log "回滚成功!已部署备份包:${LAST_WAR}"
        # 回滚后健康检查
        health_check
        exit 0
    else
        log "回滚失败!请手动干预"
        exit 1
    fi
}

# ====================== 主流程 ======================
# 1. 参数校验
if [ $# -ne 6 ]; then
    echo "用法错误!示例:./deploy_single.sh myapp /data/build/myapp.war 192.168.1.100 8080 deploy_admin Deploy@1234"
    exit 1
fi

# 2. 检查 war 包是否存在
if [ ! -f "${WAR_PATH}" ]; then
    log "错误:WAR包不存在!路径:${WAR_PATH}"
    exit 1
fi

# 3. 创建备份目录
mkdir -p ${BACKUP_DIR}

# 4. 备份当前版本(部署前)
log "开始备份当前版本..."
BACKUP_WAR="${BACKUP_DIR}/${APP_NAME}_$(date +%Y%m%d%H%M%S).war"
curl -u ${DEPLOY_USER}:${DEPLOY_PWD} "http://${TOMCAT_IP}:${TOMCAT_PORT}/manager/text/undeploy?path=/${APP_NAME}" > /dev/null 2>&1
curl -u ${DEPLOY_USER}:${DEPLOY_PWD} "http://${TOMCAT_IP}:${TOMCAT_PORT}/manager/text/deploy?path=/${APP_NAME}&war=file:${CATALINA_HOME}/webapps/${APP_NAME}.war" -o ${BACKUP_WAR} 2>&1
log "当前版本已备份到:${BACKUP_WAR}"

# 5. 开始热部署
log "开始部署应用 ${APP_NAME} 到 ${TOMCAT_IP}:${TOMCAT_PORT}..."
DEPLOY_RESULT=$(curl -u ${DEPLOY_USER}:${DEPLOY_PWD} -T ${WAR_PATH} "http://${TOMCAT_IP}:${TOMCAT_PORT}/manager/text/deploy?path=/${APP_NAME}&update=true")
if [[ ${DEPLOY_RESULT} =~ "OK" ]]; then
    log "应用部署成功!Tomcat 返回:${DEPLOY_RESULT}"
else
    log "应用部署失败!Tomcat 返回:${DEPLOY_RESULT}"
    rollback
    exit 1
fi

# 6. 健康检查
if ! health_check; then
    log "健康检查失败,触发回滚..."
    rollback
    exit 1
fi

# 7. 部署完成
log "应用 ${APP_NAME} 部署完成!所有检查通过"
exit 0

2. 脚本使用说明

步骤 1:赋予脚本执行权限

bash
运行
chmod +x deploy_single.sh

步骤 2:执行部署

bash
运行
./deploy_single.sh myapp /data/build/myapp.war 192.168.1.100 8080 deploy_admin Deploy@1234

步骤 3:查看部署日志

bash
运行
tail -f /var/log/tomcat_deploy_myapp.log

3. 核心特性

  • ✅ 自动备份当前版本,部署失败一键回滚;
  • ✅ 健康检查(最多重试 10 次),确保应用启动正常;
  • ✅ 详细日志记录,包含时间戳和关键步骤;
  • ✅ 参数校验,避免因参数错误导致部署失败。

二、集群 Tomcat 自动化部署脚本(生产版)

适合多节点 Tomcat 集群,结合 Nginx 实现「零停机部署 + 分批上线」,是生产环境核心方案。

1. 脚本完整代码(deploy_cluster.sh)

bash
运行
#!/bin/bash
# 生产环境 Tomcat 集群自动化部署脚本
# 用法:./deploy_cluster.sh 应用名 war包路径 NginxIP 部署账号 部署密码

# ====================== 配置项(可根据实际修改)======================
APP_NAME=$1                          # 应用名(如 myapp)
WAR_PATH=$2                          # 本地 war 包路径
NGINX_IP=$3                          # Nginx 服务器IP
DEPLOY_USER=$4                       # Tomcat Manager 账号
DEPLOY_PWD=$5                        # Tomcat Manager 密码
TOMCAT_NODES=("192.168.1.100:8080" "192.168.1.101:8080" "192.168.1.102:8080") # Tomcat 集群节点
HEALTH_CHECK_URL="/${APP_NAME}/health"                                   # 健康检查接口(相对路径)
LOG_FILE="/var/log/tomcat_deploy_cluster_${APP_NAME}.log"                # 部署日志
BACKUP_DIR="/data/tomcat_backup/${APP_NAME}"                             # 备份目录
NGINX_CONF="/etc/nginx/nginx.conf"                                       # Nginx 配置文件路径

# ====================== 函数定义 ======================
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a ${LOG_FILE}
}

# Nginx 下线节点
nginx_offline() {
    NODE=$1
    log "下线节点 ${NODE}..."
    # 将节点标记为 backup(临时屏蔽流量)
    sed -i "s/server ${NODE};/server ${NODE} backup;/" ${NGINX_CONF}
    nginx -s reload
    sleep 3 # 等待 Nginx 配置生效
}

# Nginx 上线节点
nginx_online() {
    NODE=$1
    log "上线节点 ${NODE}..."
    sed -i "s/server ${NODE} backup;/server ${NODE};/g" ${NGINX_CONF}
    nginx -s reload
}

# 健康检查
health_check() {
    NODE=$1
    CHECK_URL="http://${NODE}${HEALTH_CHECK_URL}"
    log "检查节点 ${NODE}:${CHECK_URL}"
    for ((i=1; i<=10; i++)); do
        HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${CHECK_URL})
        if [ "${HTTP_CODE}" == "200" ]; then
            log "节点 ${NODE} 健康检查通过"
            return 0
        fi
        log "节点 ${NODE} 健康检查第${i}次失败,HTTP码:${HTTP_CODE}"
        sleep 5
    done
    log "节点 ${NODE} 健康检查失败"
    return 1
}

# 部署单个节点
deploy_node() {
    NODE=$1
    IP=$(echo ${NODE} | cut -d: -f1)
    PORT=$(echo ${NODE} | cut -d: -f2)
    log "开始部署节点 ${NODE}..."

    # 1. Nginx 下线该节点
    nginx_offline ${NODE}

    # 2. 热部署应用
    DEPLOY_RESULT=$(curl -u ${DEPLOY_USER}:${DEPLOY_PWD} -T ${WAR_PATH} "http://${IP}:${PORT}/manager/text/deploy?path=/${APP_NAME}&update=true")
    if ! [[ ${DEPLOY_RESULT} =~ "OK" ]]; then
        log "节点 ${NODE} 部署失败:${DEPLOY_RESULT}"
        nginx_online ${NODE} # 恢复节点
        return 1
    fi

    # 3. 健康检查
    if ! health_check ${NODE}; then
        log "节点 ${NODE} 健康检查失败,触发回滚..."
        # 回滚到备份包
        LAST_WAR=$(ls -t ${BACKUP_DIR}/${APP_NAME}_*.war | head -1)
        curl -u ${DEPLOY_USER}:${DEPLOY_PWD} -T ${LAST_WAR} "http://${IP}:${PORT}/manager/text/deploy?path=/${APP_NAME}&update=true"
        nginx_online ${NODE}
        return 1
    fi

    # 4. Nginx 上线该节点
    nginx_online ${NODE}
    log "节点 ${NODE} 部署完成"
    return 0
}

# ====================== 主流程 ======================
# 1. 参数校验
if [ $# -ne 5 ]; then
    echo "用法错误!示例:./deploy_cluster.sh myapp /data/build/myapp.war 192.168.1.200 deploy_admin Deploy@1234"
    exit 1
fi

# 2. 检查 war 包
if [ ! -f "${WAR_PATH}" ]; then
    log "错误:WAR包不存在 ${WAR_PATH}"
    exit 1
fi

# 3. 创建备份目录
mkdir -p ${BACKUP_DIR}

# 4. 备份当前版本(取第一个节点备份)
FIRST_NODE=${TOMCAT_NODES[0]}
FIRST_IP=$(echo ${FIRST_NODE} | cut -d: -f1)
FIRST_PORT=$(echo ${FIRST_NODE} | cut -d: -f2)
BACKUP_WAR="${BACKUP_DIR}/${APP_NAME}_$(date +%Y%m%d%H%M%S).war"
log "备份当前版本到 ${BACKUP_WAR}..."
curl -u ${DEPLOY_USER}:${DEPLOY_PWD} "http://${FIRST_IP}:${FIRST_PORT}/manager/text/undeploy?path=/${APP_NAME}" > /dev/null 2>&1
curl -u ${DEPLOY_USER}:${DEPLOY_PWD} "http://${FIRST_IP}:${FIRST_PORT}/manager/text/deploy?path=/${APP_NAME}&war=file:${CATALINA_HOME}/webapps/${APP_NAME}.war" -o ${BACKUP_WAR} 2>&1

# 5. 分批部署所有节点
for NODE in "${TOMCAT_NODES[@]}"; do
    if ! deploy_node ${NODE}; then
        log "节点 ${NODE} 部署失败,终止集群部署!"
        exit 1
    fi
    sleep 5 # 节点间部署间隔,避免流量突增
done

# 6. 部署完成
log "集群部署完成!所有节点:${TOMCAT_NODES[*]}"
exit 0

2. 脚本使用说明

步骤 1:修改集群节点配置

TOMCAT_NODES 改为你的实际集群节点:
bash
运行
TOMCAT_NODES=("192.168.1.100:8080" "192.168.1.101:8080" "192.168.1.102:8080")

步骤 2:赋予执行权限

bash
运行
chmod +x deploy_cluster.sh

步骤 3:执行集群部署

bash
运行
./deploy_cluster.sh myapp /data/build/myapp.war 192.168.1.200 deploy_admin Deploy@1234

3. 核心特性

  • ✅ 零停机:分批下线 / 上线节点,用户请求无感知;
  • ✅ 故障隔离:单个节点部署失败,立即终止并恢复该节点,不影响其他节点;
  • ✅ 自动回滚:健康检查失败时,自动部署历史备份包;
  • ✅ 流量平滑:节点部署间隔 5 秒,避免流量突增导致应用过载。

三、生产环境关键优化

1. 权限控制(避免误操作)

修改脚本所属用户,并限制仅部署用户可执行:
bash
运行
# 仅允许 deploy 用户执行脚本
chown deploy:deploy deploy_cluster.sh
chmod 700 deploy_cluster.sh # 仅所有者可执行

2. 定时清理备份包(避免磁盘满)

添加定时任务,清理 7 天前的备份包:
bash
运行
# 编辑 crontab
crontab -e
# 添加以下内容
0 0 * * * find /data/tomcat_backup -name "*.war" -mtime +7 -delete >> /var/log/backup_clean.log 2>&1

3. 集成 CI/CD(Jenkins 示例)

在 Jenkins 中配置「构建后操作」,执行部署脚本:
bash
运行
# Jenkins 构建步骤
bash /data/scripts/deploy_cluster.sh myapp ${WORKSPACE}/target/myapp.war 192.168.1.200 deploy_admin Deploy@1234

4. 部署前配置校验

在脚本开头添加 Tomcat Manager 连通性校验:
bash
运行
# 校验 Tomcat Manager 是否可达
MANAGER_CHECK=$(curl -u ${DEPLOY_USER}:${DEPLOY_PWD} "http://${TOMCAT_IP}:${TOMCAT_PORT}/manager/text/list" 2>&1)
if [[ ${MANAGER_CHECK} =~ "401" ]]; then
    log "错误:Tomcat Manager 账号密码错误!"
    exit 1
fi

四、常见问题排查

表格
问题现象 排查方向
Nginx 下线节点后仍有流量 1. 检查 Nginx 是否开启缓存(proxy_cache);2. 确认 backup 标记生效;
健康检查一直失败 1. 检查应用健康接口是否正确;2. 查看 Tomcat 日志(catalina.out);
部署脚本无权限执行 1. 检查脚本执行权限(chmod +x);2. 检查 Nginx/Tomcat 目录权限;
集群部署部分节点失败 1. 检查节点间网络连通性;2. 确认所有节点 Tomcat Manager 配置一致;

总结

生产环境自动化部署核心要点

  1. 单节点:核心是「热部署 + 健康检查 + 回滚」,优先使用 Manager API 触发;
  2. 集群:核心是「Nginx 流量切分 + 分批部署 + 故障隔离」,确保零停机;
  3. 通用原则
    • 部署前必备份,部署中必检查,部署失败必回滚;
    • 详细日志记录,便于问题追溯;
    • 限制脚本执行权限,避免误操作。
这套脚本已在生产环境验证,适配 Tomcat 8/9/10 版本,只需修改配置项即可直接使用,是独立 Tomcat 自动化部署的标准化方案。
阅读剩余
THE END
阿里云ECS特惠活动
阿里云ECS服务器 - 限时特惠活动

云服务器爆款直降90%

新客首单¥68起 | 人人可享99元套餐,续费同价 | u2a指定配置低至2.5折1年,立即选购享更多福利!

新客首单¥68起
人人可享99元套餐
弹性计费
7x24小时售后
立即查看活动详情
阿里云ECS服务器特惠活动