Files
happy-life-star/backend-single/deploy.sh
T

380 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 情绪博物馆后端服务部署脚本
# 支持本地部署和远程部署到服务器 101.200.208.45
set -e
# 配置变量
APP_NAME="emotion-museum-single"
JAR_NAME="backend-single-1.0.0.jar"
JAR_PATH="./target/${JAR_NAME}"
LOG_DIR="./logs/"
PID_FILE="/tmp/${APP_NAME}.pid"
JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${LOG_DIR}/heapdump.hprof"
# 远程服务器配置
REMOTE_HOST="101.200.208.45"
REMOTE_USER="root"
REMOTE_DIR="/data/programs/emotion-museum"
REMOTE_LOG_DIR="/data/logs/emotion-museum"
REMOTE_JAR_NAME="emotion-single-1.0.0.jar"
SPRING_PROFILE="test"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查并构建项目
build_project() {
log_info "开始构建项目..."
# 检查 Maven 是否安装
if ! command -v mvn > /dev/null 2>&1; then
log_error "未找到Maven命令,请确保已安装Maven"
exit 1
fi
# 执行 Maven 构建
log_info "执行: mvn clean package -DskipTests"
if ! mvn clean package -DskipTests; then
log_error "项目构建失败"
exit 1
fi
# 检查 JAR 文件是否生成
if [ ! -f "$JAR_PATH" ]; then
log_error "项目构建失败,未找到JAR文件: $JAR_PATH"
log_error "请检查 Maven 构建输出"
exit 1
fi
log_info "✅ 项目构建成功: $JAR_PATH"
log_info "文件大小: $(ls -lh $JAR_PATH | awk '{print $5}')"
}
# 检查 jar 文件是否存在
check_jar() {
if [ ! -f "$JAR_PATH" ]; then
log_error "JAR 文件不存在: $JAR_PATH"
log_info "请先执行打包命令: mvn clean package"
exit 1
fi
log_info "JAR 文件检查通过: $JAR_PATH"
}
# 创建日志目录
create_log_dir() {
if [ ! -d "$LOG_DIR" ]; then
log_info "创建日志目录: $LOG_DIR"
mkdir -p "$LOG_DIR"
fi
}
# 本地部署 - 停止旧服务
stop_local_service() {
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then
log_info "停止旧服务 (PID: $PID)"
kill "$PID"
# 等待服务停止
for i in {1..30}; do
if ! ps -p "$PID" > /dev/null 2>&1; then
log_info "服务已停止"
break
fi
sleep 1
done
# 强制停止
if ps -p "$PID" > /dev/null 2>&1; then
log_warn "强制停止服务 (PID: $PID)"
kill -9 "$PID"
fi
else
log_warn "PID 文件存在但进程不存在,清理 PID 文件"
fi
rm -f "$PID_FILE"
else
log_info "没有找到 PID 文件,服务可能未运行"
fi
}
# 本地部署 - 启动新服务
start_local_service() {
log_info "启动本地服务..."
# 启动命令
nohup java $JAVA_OPTS \
-Dspring.profiles.active=$SPRING_PROFILE \
-Dlogging.file.path=$LOG_DIR \
-Dlogging.file.name=$LOG_DIR/application.log \
-jar "$JAR_PATH" \
> "$LOG_DIR/startup.log" 2>&1 &
# 保存 PID
echo $! > "$PID_FILE"
log_info "服务启动中,PID: $(cat $PID_FILE)"
log_info "启动日志: $LOG_DIR/startup.log"
log_info "应用日志: $LOG_DIR/application.log"
}
# 远程部署 - 上传文件到服务器
# 参数: $1 - 可选,指定要上传的额外文件(如 deploy-server.sh
deploy_to_remote() {
UPLOAD_SCRIPT="$2"
log_info "开始远程部署到 $REMOTE_HOST..."
# 检查并构建项目
build_project
# 检查 jar 文件
check_jar
# 创建远程目录
log_info "创建远程目录..."
if ! ssh $REMOTE_USER@$REMOTE_HOST "mkdir -p $REMOTE_DIR"; then
log_error "创建远程目录失败: $REMOTE_DIR"
exit 1
fi
if ! ssh $REMOTE_USER@$REMOTE_HOST "mkdir -p $REMOTE_LOG_DIR"; then
log_error "创建远程日志目录失败: $REMOTE_LOG_DIR"
exit 1
fi
# 上传 jar 文件并重命名
log_info "上传 JAR 文件到远程服务器..."
log_info "本地文件: $JAR_PATH"
log_info "远程路径: $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/$REMOTE_JAR_NAME"
if ! scp "$JAR_PATH" $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/$REMOTE_JAR_NAME; then
log_error "上传 JAR 文件失败"
log_error "请检查:"
log_error " 1. SSH 连接是否正常: ssh $REMOTE_USER@$REMOTE_HOST 'ls -la $REMOTE_DIR'"
log_error " 2. 本地文件是否存在: ls -la $JAR_PATH"
log_error " 3. 远程目录权限: ssh $REMOTE_USER@$REMOTE_HOST 'ls -la $REMOTE_DIR'"
exit 1
fi
log_info "✅ JAR 文件上传成功"
# 验证远程文件
log_info "验证远程文件..."
if ! ssh $REMOTE_USER@$REMOTE_HOST "ls -lh $REMOTE_DIR/$REMOTE_JAR_NAME"; then
log_error "远程文件验证失败"
exit 1
fi
# 如果指定了额外文件,则上传
if [ -n "$UPLOAD_SCRIPT" ] && [ -f "$UPLOAD_SCRIPT" ]; then
log_info "上传指定文件到远程服务器: $UPLOAD_SCRIPT"
if ! scp "$UPLOAD_SCRIPT" $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/; then
log_error "上传文件失败: $UPLOAD_SCRIPT"
exit 1
fi
log_info "✅ 文件上传成功: $UPLOAD_SCRIPT"
# 如果是脚本文件,设置执行权限
REMOTE_FILENAME=$(basename "$UPLOAD_SCRIPT")
if [[ "$REMOTE_FILENAME" == *.sh ]]; then
log_info "设置远程脚本权限..."
ssh $REMOTE_USER@$REMOTE_HOST "chmod +x $REMOTE_DIR/$REMOTE_FILENAME"
fi
else
log_info "跳过部署脚本上传(服务器已存在)"
fi
# 在远程服务器上执行部署
log_info "在远程服务器上执行部署..."
if ! ssh $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_DIR && ./deploy-server.sh $SPRING_PROFILE"; then
log_error "远程部署脚本执行失败"
exit 1
fi
log_info "✅ 远程部署完成!"
show_remote_info
}
# 本地部署 - 检查服务状态
check_local_status() {
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then
log_info "服务运行中 (PID: $PID)"
return 0
else
log_error "PID 文件存在但进程不存在"
return 1
fi
else
log_error "PID 文件不存在,服务未运行"
return 1
fi
}
# 本地部署 - 等待服务启动
wait_for_local_startup() {
log_info "等待服务启动..."
for i in {1..60}; do
if check_local_status > /dev/null 2>&1; then
# 检查端口是否监听(使用 19089 端口)
if netstat -tlnp 2>/dev/null | grep -q ":19089.*LISTEN"; then
log_info "服务启动成功!"
return 0
fi
fi
sleep 2
done
log_error "服务启动超时,请检查日志: $LOG_DIR/startup.log"
return 1
}
# 本地部署 - 显示服务信息
show_local_info() {
log_info "=== 本地服务信息 ==="
log_info "应用名称: $APP_NAME"
log_info "JAR 文件: $JAR_PATH"
log_info "日志目录: $LOG_DIR"
log_info "PID 文件: $PID_FILE"
log_info "Java 参数: $JAVA_OPTS"
log_info "Spring Profile: $SPRING_PROFILE"
if check_local_status > /dev/null 2>&1; then
PID=$(cat "$PID_FILE")
log_info "服务状态: 运行中 (PID: $PID)"
# 显示内存使用情况
if command -v jstat > /dev/null 2>&1; then
log_info "内存使用情况:"
jstat -gc "$PID" | head -2
fi
else
log_info "服务状态: 未运行"
fi
}
# 远程部署 - 显示服务信息
show_remote_info() {
log_info "=== 远程服务信息 ==="
log_info "服务器地址: $REMOTE_HOST"
log_info "部署目录: $REMOTE_DIR"
log_info "日志目录: $REMOTE_LOG_DIR"
log_info "Spring Profile: $SPRING_PROFILE"
# 检查远程服务状态
log_info "检查远程服务状态..."
ssh $REMOTE_USER@$REMOTE_HOST "ps aux | grep $REMOTE_JAR_NAME | grep -v grep" || log_info "远程服务未运行"
}
# 本地部署 - 主函数
local_deploy() {
log_info "开始本地部署 $APP_NAME 服务..."
# 检查并构建项目
build_project
# 检查 jar 文件
check_jar
# 创建日志目录
create_log_dir
# 停止旧服务
stop_local_service
# 启动新服务
start_local_service
# 等待启动
if wait_for_local_startup; then
log_info "本地部署成功!"
show_local_info
else
log_error "本地部署失败!"
exit 1
fi
}
# 处理命令行参数
case "${1:-deploy}" in
"deploy")
local_deploy
;;
"remote")
deploy_to_remote "$@"
;;
"build")
build_project
;;
"start")
# 检查并构建项目
build_project
check_jar
create_log_dir
start_local_service
wait_for_local_startup
;;
"stop")
stop_local_service
;;
"restart")
stop_local_service
sleep 2
# 检查并构建项目
build_project
check_jar
create_log_dir
start_local_service
wait_for_local_startup
;;
"status")
show_local_info
;;
"remote-status")
show_remote_info
;;
"logs")
if [ -f "$LOG_DIR/application.log" ]; then
tail -f "$LOG_DIR/application.log"
else
log_error "日志文件不存在: $LOG_DIR/application.log"
fi
;;
*)
echo "用法: $0 {deploy|remote [文件名]|build|start|stop|restart|status|remote-status|logs}"
echo " deploy - 本地部署服务(默认)"
echo " remote - 远程部署到服务器(仅上传JAR)"
echo " remote [文件名] - 远程部署并上传指定文件(如 deploy-server.sh"
echo " build - 构建项目"
echo " start - 启动本地服务"
echo " stop - 停止本地服务"
echo " restart - 重启本地服务"
echo " status - 查看本地服务状态"
echo " remote-status - 查看远程服务状态"
echo " logs - 查看本地实时日志"
echo ""
echo "示例:"
echo " $0 remote # 仅上传JAR并部署"
echo " $0 remote deploy-server.sh # 同时上传部署脚本"
exit 1
;;
esac