#!/bin/bash # 情绪博物馆后端服务部署脚本 # 支持本地部署和远程部署到服务器 101.200.208.45 set -e # 配置变量 APP_NAME="emotion-museum-single" JAR_NAME="emotion-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" 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 "检查项目构建状态..." # 检查是否已经构建过并且JAR文件存在 if [ -f "$JAR_PATH" ]; then log_info "JAR 文件已存在: $JAR_PATH" return 0 fi # 执行Maven构建 log_info "开始构建项目..." if command -v mvn > /dev/null 2>&1; then mvn clean package -DskipTests if [ -f "$JAR_PATH" ]; then log_info "项目构建成功: $JAR_PATH" return 0 else log_error "项目构建失败,未找到JAR文件: $JAR_PATH" exit 1 fi else log_error "未找到Maven命令,请确保已安装Maven" exit 1 fi } # 检查 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" } # 远程部署 - 上传文件到服务器 deploy_to_remote() { log_info "开始远程部署到 $REMOTE_HOST..." # 检查并构建项目 build_project # 检查 jar 文件 check_jar # 创建远程目录 log_info "创建远程目录..." ssh $REMOTE_USER@$REMOTE_HOST "mkdir -p $REMOTE_DIR" ssh $REMOTE_USER@$REMOTE_HOST "mkdir -p $REMOTE_LOG_DIR" # 上传 jar 文件 log_info "上传 JAR 文件到远程服务器..." scp "$JAR_PATH" $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/ # 上传部署脚本 log_info "上传部署脚本到远程服务器..." scp "./deploy-server.sh" $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/ # 设置权限 ssh $REMOTE_USER@$REMOTE_HOST "chmod +x $REMOTE_DIR/deploy-server.sh" # 在远程服务器上执行部署 log_info "在远程服务器上执行部署..." ssh $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_DIR && ./deploy-server.sh $SPRING_PROFILE" log_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 $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 - 远程部署到服务器" echo " build - 构建项目" echo " start - 启动本地服务" echo " stop - 停止本地服务" echo " restart - 重启本地服务" echo " status - 查看本地服务状态" echo " remote-status - 查看远程服务状态" echo " logs - 查看本地实时日志" exit 1 ;; esac