#!/bin/bash # 情绪博物馆后端服务部署脚本 # 使用生产环境配置,日志保存到 /data/logs/emotion-museum/single set -e # 配置变量 APP_NAME="emotion-museum-single" JAR_NAME="emotion-single-1.0.0.jar" JAR_PATH="./${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" # 颜色输出 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" } # 检查 jar 文件是否存在 check_jar() { if [ ! -f "$JAR_PATH" ]; then log_error "JAR 文件不存在: $JAR_PATH" log_info "请先执行打包命令: mvn clean package -Pprod" 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_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_service() { log_info "启动新服务..." # 启动命令 nohup java $JAVA_OPTS \ -Dspring.profiles.active=prod \ -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" } # 检查服务状态 check_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_startup() { log_info "等待服务启动..." for i in {1..60}; do if check_status > /dev/null 2>&1; then # 检查端口是否监听(假设使用 8080 端口) if netstat -tlnp 2>/dev/null | grep -q ":8080.*LISTEN"; then log_info "服务启动成功!" return 0 fi fi sleep 2 done log_error "服务启动超时,请检查日志: $LOG_DIR/startup.log" return 1 } # 显示服务信息 show_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" if check_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 } # 主函数 main() { log_info "开始部署 $APP_NAME 服务..." # 检查 jar 文件 check_jar # 创建日志目录 create_log_dir # 停止旧服务 stop_service # 启动新服务 start_service # 等待启动 if wait_for_startup; then log_info "部署成功!" show_info else log_error "部署失败!" exit 1 fi } # 处理命令行参数 case "${1:-deploy}" in "deploy") main ;; "start") check_jar create_log_dir start_service wait_for_startup ;; "stop") stop_service ;; "restart") stop_service sleep 2 check_jar create_log_dir start_service wait_for_startup ;; "status") show_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|start|stop|restart|status|logs}" echo " deploy - 部署服务(默认)" echo " start - 启动服务" echo " stop - 停止服务" echo " restart - 重启服务" echo " status - 查看服务状态" echo " logs - 查看实时日志" exit 1 ;; esac