#!/bin/bash
UPLOAD_JAR_NAME="maycamp-backend.jar"
RUN_JAR_NAME="maycamp-backend-prod.jar"
BACKUP_DIR="backups"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
get_timestamp() {
date +"%Y%m%d-%H%M"
}
create_backup_dir() {
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR"
echo "创建备份目录: $BACKUP_DIR"
fi
}
backup_current_jar() {
if [ -f "$RUN_JAR_NAME" ]; then
local timestamp=$(get_timestamp)
local backup_name="${UPLOAD_JAR_NAME}-${timestamp}"
local backup_path="$BACKUP_DIR/$backup_name"
cp "$RUN_JAR_NAME" "$backup_path"
echo "已备份当前运行jar包: $backup_path"
show_backup_stats
else
echo "当前运行jar包 $RUN_JAR_NAME 不存在,跳过备份"
fi
}
show_backup_stats() {
if [ -d "$BACKUP_DIR" ]; then
local backup_count=$(ls -1 "$BACKUP_DIR"/* 2>/dev/null | wc -l)
echo "当前备份总数: $backup_count 个文件"
fi
}
find_pid() {
local pid=$(ps -ef | grep "$RUN_JAR_NAME" | grep -v grep | awk '{print $2}')
if [ -z "$pid" ]; then
echo "未找到 $RUN_JAR_NAME 的运行实例,将直接启动新版本"
return 1
fi
echo $pid
return 0
}
graceful_shutdown() {
local pid=$1
if [ -n "$pid" ]; then
echo "正在停止应用进程"
kill -15 $pid
echo "已发送优雅停止信号"
return 0
else
echo "没有需要停止的进程"
return 1
fi
}
wait_for_stop() {
local pid=$1
local timeout=60
local count=0
if [ -z "$pid" ]; then
echo "没有需要等待停止的进程"
return 0
fi
while [ $count -lt $timeout ]; do
if ! ps -p $pid > /dev/null 2>&1; then
echo "进程 $pid 已停止"
return 0
fi
count=$((count + 2))
echo "等待进程停止... ($((count))/$timeout 秒)"
sleep 2
done
echo -e "${RED} 等待超时,进程 $pid 仍未停止,尝试强制终止... ${NC}"
kill -9 $pid 2>/dev/null
sleep 2
if ps -p $pid > /dev/null 2>&1; then
echo -e "${RED} 错误: 无法终止进程 $pid ${NC}"
return 1
else
echo -e "${YELLOW} 进程 $pid 已强制终止 ${NC}"
return 0
fi
}
check_upload_jar() {
if [ ! -f "$UPLOAD_JAR_NAME" ]; then
echo "错误: 上传的jar包 $UPLOAD_JAR_NAME 不存在!"
echo "请确保 $UPLOAD_JAR_NAME 文件在当前目录"
exit 1
fi
echo "找到上传的jar包: $UPLOAD_JAR_NAME"
}
start_app() {
echo "正在部署新版本..."
echo "复制 $UPLOAD_JAR_NAME -> $RUN_JAR_NAME"
cp "$UPLOAD_JAR_NAME" "$RUN_JAR_NAME"
echo "启动应用中..."
nohup java -jar "$RUN_JAR_NAME" > console.log 2>&1 &
local new_pid=$!
sleep 5
if ps -p $new_pid > /dev/null 2>&1; then
echo -e "${GREEN} 应用启动成功! PID: $new_pid ${NC}"
return 0
else
echo -e "${RED} 错误: 应用启动失败,请检查 console.log 日志 ${NC}"
return 1
fi
}
show_deployment_info() {
echo "=========================================="
echo "部署完成时间: $(date)"
echo "上传的jar包: $UPLOAD_JAR_NAME"
echo "运行的jar包: $RUN_JAR_NAME"
echo "备份目录: $BACKUP_DIR"
echo "=========================================="
}
show_backup_list() {
if [ -d "$BACKUP_DIR" ] && [ "$(ls -A $BACKUP_DIR 2>/dev/null)" ]; then
echo "当前备份文件列表:"
ls -lt "$BACKUP_DIR"/*.jar 2>/dev/null | head -10 | awk '{print " " $6 " " $7 " " $8 " " $9}'
else
echo "当前没有备份文件"
fi
}
main() {
echo "开始部署流程..."
echo "=========================================="
echo "上传的jar包: $UPLOAD_JAR_NAME"
echo "运行的jar包: $RUN_JAR_NAME"
echo "备份目录: $BACKUP_DIR"
echo "开始时间: $(date)"
echo "=========================================="
create_backup_dir
check_upload_jar
backup_current_jar
local pid=$(find_pid)
if [ -n "$pid" ] && [ "$pid" != "1" ]; then
echo "找到运行中的实例: PID $pid"
graceful_shutdown $pid
wait_for_stop $pid
else
echo "没有运行中的实例,直接启动新版本"
fi
if start_app; then
echo -e "${GREEN} 部署成功! ${NC}"
else
echo -e "${RED} 部署失败! ${NC}"
exit 1
fi
show_deployment_info
show_backup_list
}
main