Jenkins备份及回滚方式

PS:备份脚本存放位置(使用时将脚本放置环境服务包下)注意权限问题

在使用前备份脚本和回滚脚本需要根据实际的服务名称进行修改,并创建备份目录

使用SSH Pubishers执行脚本

执行脚本后,备份文件存放位置(以服务名称为文件,服务加时间戳为文件版本)

根据构建时间给予备份文件

回滚jar

备份脚本

复制代码
#!/bin/bash
set -e  # 出错立即退出,避免静默失败

# ========== 备份配置项(根据实际修改) ==========
APP_NAME="admin"          # 应用名称
ONLINE_APP_DIR="/home/work/app/service/xxx/"       # 线上应用包目录
BACKUP_DIR="/home/work/app/backup/xxx/"    # 备份目录
RETENTION_DAYS=0                 # 备份保留天数
AUDIT_LOG="/home/work/soft/logs/backup_audit.log"  # 备份审计日志

# ========== 核心逻辑 ==========
# 1. 生成精确到秒的时间戳
TIMESTAMP=$(date +%Y%m%d%H%M%S)
# 2. 定义文件路径
ONLINE_APP_PATH="${ONLINE_APP_DIR}/${APP_NAME}.jar"
BACKUP_APP_PATH="${BACKUP_DIR}/${APP_NAME}-${TIMESTAMP}.jar"

# 3. 校验线上包是否存在
if [ ! -f "${ONLINE_APP_PATH}" ]; then
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 线上包 ${ONLINE_APP_PATH} 不存在,备份失败!" >> ${AUDIT_LOG}
    echo "ERROR: 线上包不存在,备份失败!"
    exit 1
fi

# 4. 执行备份(-p 保留文件属性:权限、时间、属主)
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 开始备份 ${ONLINE_APP_PATH} -> ${BACKUP_APP_PATH}" >> ${AUDIT_LOG}
cp -p ${ONLINE_APP_PATH} ${BACKUP_APP_PATH}


# 5. 校验备份是否成功(对比文件大小)
ONLINE_SIZE=$(du -b ${ONLINE_APP_PATH} | awk '{print $1}')
BACKUP_SIZE=$(du -b ${BACKUP_APP_PATH} | awk '{print $1}')
if [ "${ONLINE_SIZE}" != "${BACKUP_SIZE}" ]; then
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 备份包大小不一致,备份失败!" >> ${AUDIT_LOG}
    rm -f ${BACKUP_APP_PATH}  # 删除损坏的备份包
    exit 1
fi

# 6. 清理过期备份
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 清理${RETENTION_DAYS}天前的备份..." >> ${AUDIT_LOG}
find ${BACKUP_DIR} -name "${APP_NAME}-*.jar" -mtime +${RETENTION_DAYS} -delete >> ${AUDIT_LOG} 2>&1

# 7. 记录审计日志
echo "[$(date +'%Y-%m-%d %H:%M:%S')] SUCCESS: 备份成功,备份包路径:${BACKUP_APP_PATH}" >> ${AUDIT_LOG}

# 8. 输出成功信息(供Jenkins日志查看)
echo "备份成功!"
echo "备份包路径:${BACKUP_APP_PATH}"
echo "当前备份列表(按时间倒序):"
ls -lh ${BACKUP_DIR}/${APP_NAME}-*.jar | sort -k9r

exit 0

回滚脚本

复制代码
#!/bin/bash
set -e  # 出错立即退出,避免静默失败

# ========== 备份配置项(根据实际修改) ==========
APP_NAME="admin"          # 应用名称
ONLINE_APP_DIR="/home/work/app/service/xxx/"       # 线上应用包目录
BACKUP_DIR="/home/work/app/backup/xxx/"    # 备份目录
RETENTION_DAYS=0                 # 备份保留天数
AUDIT_LOG="/home/work/soft/logs/backup_audit.log"  # 备份审计日志

# ========== 核心逻辑 ==========
# 1. 生成精确到秒的时间戳
TIMESTAMP=$(date +%Y%m%d%H%M%S)
# 2. 定义文件路径
ONLINE_APP_PATH="${ONLINE_APP_DIR}/${APP_NAME}.jar"
BACKUP_APP_PATH="${BACKUP_DIR}/${APP_NAME}-${TIMESTAMP}.jar"

# 3. 校验线上包是否存在
if [ ! -f "${ONLINE_APP_PATH}" ]; then
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 线上包 ${ONLINE_APP_PATH} 不存在,备份失败!" >> ${AUDIT_LOG}
    echo "ERROR: 线上包不存在,备份失败!"
    exit 1
fi

# 4. 执行备份(-p 保留文件属性:权限、时间、属主)
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 开始备份 ${ONLINE_APP_PATH} -> ${BACKUP_APP_PATH}" >> ${AUDIT_LOG}
cp -p ${ONLINE_APP_PATH} ${BACKUP_APP_PATH}


# 5. 校验备份是否成功(对比文件大小)
ONLINE_SIZE=$(du -b ${ONLINE_APP_PATH} | awk '{print $1}')
BACKUP_SIZE=$(du -b ${BACKUP_APP_PATH} | awk '{print $1}')
if [ "${ONLINE_SIZE}" != "${BACKUP_SIZE}" ]; then
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 备份包大小不一致,备份失败!" >> ${AUDIT_LOG}
    rm -f ${BACKUP_APP_PATH}  # 删除损坏的备份包
    exit 1
fi

# 6. 清理过期备份
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 清理${RETENTION_DAYS}天前的备份..." >> ${AUDIT_LOG}
find ${BACKUP_DIR} -name "${APP_NAME}-*.jar" -mtime +${RETENTION_DAYS} -delete >> ${AUDIT_LOG} 2>&1

# 7. 记录审计日志
echo "[$(date +'%Y-%m-%d %H:%M:%S')] SUCCESS: 备份成功,备份包路径:${BACKUP_APP_PATH}" >> ${AUDIT_LOG}

# 8. 输出成功信息(供Jenkins日志查看)
echo "备份成功!"
echo "备份包路径:${BACKUP_APP_PATH}"
echo "当前备份列表(按时间倒序):"
ls -lh ${BACKUP_DIR}/${APP_NAME}-*.jar | sort -k9r

exit 0
[root@rocky9-0 scripts]# cat rollback_service.sh 
#!/bin/bash
set -e  # 出错立即退出,避免静默失败

# ========== 回滚配置项(和备份脚本完全对齐) ==========
APP_NAME="XXX"          # 应用名称
ONLINE_APP_DIR="/home/lyszwork/app/service/XXX/"       # 线上应用包目录
BACKUP_DIR="/home/lyszwork/app/backup/XXX"    # 备份目录
AUDIT_LOG="/home/lyszwork/soft/logs/rollback_service.log"  # 复用备份审计日志

# 【核心配置】应用启停命令(
STOP_APP_CMD="sh /home/lyszwork/app/service/common-service-center/deploy.sh stop"
START_APP_CMD="sh /home/lyszwork/app/service/common-service-center/deploy.sh start"

# ========== 核心回滚逻辑 ==========
# 1. 前置校验:检查备份目录是否存在
if [ ! -d "${BACKUP_DIR}" ]; then
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 备份目录 ${BACKUP_DIR} 不存在!" >> ${AUDIT_LOG}
    echo "ERROR: 备份目录不存在,无法回滚!"
    exit 1
fi

# 2. 列出所有备份包(按时间倒序),筛选上一个版本
# 获取备份包列表(排除当前行),按时间戳降序排列
BACKUP_LIST=($(ls ${BACKUP_DIR}/${APP_NAME}-*.jar 2>/dev/null | sort -r))
if [ ${#BACKUP_LIST[@]} -eq 0 ]; then
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 未找到任何备份包!" >> ${AUDIT_LOG}
    echo "ERROR: 无备份包可回滚!"
    exit 1
fi

# 选择"上一个版本"(列表第一个即为最新备份,也就是要回滚的目标版本)
TARGET_BACKUP=${BACKUP_LIST[0]}
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 选定回滚版本:${TARGET_BACKUP}" >> ${AUDIT_LOG}
echo "✅ 选定回滚版本:${TARGET_BACKUP}"

# 3. 备份当前线上包(防止回滚失败)
CURRENT_TIMESTAMP=$(date +%Y%m%d%H%M%S)
BACKUP_BEFORE_ROLLBACK="${BACKUP_DIR}/${APP_NAME}-current-before-rollback-${CURRENT_TIMESTAMP}.jar"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 备份当前线上包到 ${BACKUP_BEFORE_ROLLBACK}" >> ${AUDIT_LOG}
cp -p ${ONLINE_APP_DIR}/${APP_NAME}.jar ${BACKUP_BEFORE_ROLLBACK} 2>/dev/null || {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: 当前线上包不存在,直接使用备份包覆盖!" >> ${AUDIT_LOG}
}

# 4. 停止应用(避免Jar包被占用)
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 停止应用 ${APP_NAME}..." >> ${AUDIT_LOG}
echo "🔴 停止应用中..."
${STOP_APP_CMD} || {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: 应用停止命令执行失败(可能应用已停止)" >> ${AUDIT_LOG}
    echo "⚠️  应用停止命令执行失败(可能应用已停止),继续回滚..."
}

# 5. 执行回滚:替换线上Jar包
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 开始回滚,替换线上包..." >> ${AUDIT_LOG}
echo "🔄 执行回滚替换Jar包..."
cp -p ${TARGET_BACKUP} ${ONLINE_APP_DIR}/${APP_NAME}.jar

# 校验回滚是否成功(对比文件大小)
BACKUP_SIZE=$(du -b ${TARGET_BACKUP} | awk '{print $1}')
ROLLBACK_SIZE=$(du -b ${ONLINE_APP_DIR}/${APP_NAME}.jar | awk '{print $1}')
if [ "${BACKUP_SIZE}" != "${ROLLBACK_SIZE}" ]; then
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 回滚包大小不一致,回滚失败!" >> ${AUDIT_LOG}
    # 回滚失败:恢复之前备份的当前包
    cp -p ${BACKUP_BEFORE_ROLLBACK} ${ONLINE_APP_DIR}/${APP_NAME}.jar 2>/dev/null
    rm -f ${BACKUP_BEFORE_ROLLBACK}
    echo "❌ 回滚失败,已恢复原线上包!"
    exit 1
fi

# 6. 启动应用
echo "[$(date +'%Y-%m-%d %H:%M:%S')] INFO: 启动应用 ${APP_NAME}..." >> ${AUDIT_LOG}
echo "🟢 启动应用中..."
${START_APP_CMD} || {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: 应用启动失败!" >> ${AUDIT_LOG}
    echo "❌ 应用启动失败,请手动检查!"
    exit 1
}

# 7. 记录成功日志
echo "[$(date +'%Y-%m-%d %H:%M:%S')] SUCCESS: 回滚完成!目标版本:${TARGET_BACKUP}" >> ${AUDIT_LOG}
echo -e "\n✅ 回滚成功!"
echo "📌 回滚版本:${TARGET_BACKUP}"
echo "📌 线上包路径:${ONLINE_APP_DIR}/${APP_NAME}.jar"
echo "📌 请检查应用日志,确认服务正常运行!"

exit 0
相关推荐
真上帝的左手5 小时前
13. 搜索引擎-ES-ES集群
elasticsearch·搜索引擎·jenkins
头发多的码农5 小时前
jenkins docker ssh发布效率提升
运维·docker·jenkins
qinyia5 小时前
如何通过WisdomSSH在服务器执行一些运维任务,例如部署jenkins
运维·服务器·jenkins
小白不想白a5 小时前
Jenkins
运维·jenkins
invicinble5 小时前
nginx的基本认识
运维·nginx
阿基米东5 小时前
Traefik:为云原生而生的自动化反向代理
运维·云原生·自动化
Trouvaille ~5 小时前
【LInux】进程程序替换与shell实现:从fork到exec的完整闭环
linux·运维·c语言·c++·ssh·进程替换·基础入门
BAOYUCompany5 小时前
暴雨服务器成功中标湖南石油化工职业技术学院
运维·服务器
sdszoe49225 小时前
思科DHCP+OSPF综合实验
运维·服务器·网络·ospf·思科dhcp