#!/bin/bash # ======================================== # Java应用启动/重启脚本 # 使用方法: ./restart-java-app.sh # ======================================== # ======================================== # 配置参数 - 请根据实际情况修改 # ======================================== JAR_NAME="your-app.jar" # JAR包名称 PORT=8080 # 应用端口号 # ======================================== # 其他配置(一般不需要修改) # ======================================== JAVA_OPTS="-Xms512m -Xmx1024m" # JVM参数 LOG_FILE="app.log" # 日志文件名 PID_FILE="app.pid" # PID文件名 # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # ======================================== # 函数定义 # ======================================== # 打印带颜色的消息 print_message() { local color=$1 local message=$2 echo -e "${color}[$(date '+%Y-%m-%d %H:%M:%S')] ${message}${NC}" } # 检查JAR文件是否存在 check_jar_exists() { if [ ! -f "$JAR_NAME" ]; then print_message $RED "错误: JAR文件 '$JAR_NAME' 不存在!" print_message $YELLOW "请检查JAR_NAME配置是否正确,或确保JAR文件在当前目录下" exit 1 fi } # 检查端口是否被占用 check_port() { local port=$1 if command -v netstat >/dev/null 2>&1; then netstat -tlnp 2>/dev/null | grep ":$port " >/dev/null elif command -v ss >/dev/null 2>&1; then ss -tlnp | grep ":$port " >/dev/null else # 如果没有netstat和ss,尝试使用lsof if command -v lsof >/dev/null 2>&1; then lsof -i :$port >/dev/null 2>&1 else return 1 fi fi } # 获取运行中的应用PID get_app_pid() { if [ -f "$PID_FILE" ]; then local pid=$(cat "$PID_FILE") # 检查进程是否真的在运行 if ps -p $pid > /dev/null 2>&1; then echo $pid else # PID文件存在但进程不存在,删除PID文件 rm -f "$PID_FILE" echo "" fi else # 通过进程名查找 pgrep -f "$JAR_NAME" | head -1 fi } # 停止应用 stop_app() { local pid=$(get_app_pid) if [ -z "$pid" ]; then print_message $YELLOW "应用未运行" return 0 fi print_message $YELLOW "正在停止应用 (PID: $pid)..." # 优雅停止 kill $pid # 等待进程停止 local count=0 while [ $count -lt 30 ]; do if ! ps -p $pid > /dev/null 2>&1; then print_message $GREEN "应用已成功停止" rm -f "$PID_FILE" return 0 fi sleep 1 count=$((count + 1)) done # 如果优雅停止失败,强制停止 print_message $YELLOW "优雅停止超时,强制停止应用..." kill -9 $pid 2>/dev/null sleep 2 if ! ps -p $pid > /dev/null 2>&1; then print_message $GREEN "应用已强制停止" rm -f "$PID_FILE" return 0 else print_message $RED "停止应用失败" return 1 fi } # 启动应用 start_app() { print_message $BLUE "正在启动应用..." # 检查端口是否被占用 if check_port $PORT; then print_message $RED "端口 $PORT 已被占用,请检查是否有其他应用在使用该端口" return 1 fi # 启动应用 nohup java $JAVA_OPTS -jar "$JAR_NAME" --server.port=$PORT > "$LOG_FILE" 2>&1 & local pid=$! # 保存PID echo $pid > "$PID_FILE" # 等待应用启动 print_message $BLUE "等待应用启动..." sleep 3 # 检查进程是否还在运行 if ps -p $pid > /dev/null 2>&1; then # 检查端口是否监听 local count=0 while [ $count -lt 30 ]; do if check_port $PORT; then print_message $GREEN "应用启动成功!" print_message $GREEN "PID: $pid" print_message $GREEN "端口: $PORT" print_message $GREEN "日志文件: $LOG_FILE" return 0 fi sleep 1 count=$((count + 1)) done print_message $YELLOW "应用进程已启动,但端口 $PORT 未监听,请检查日志文件: $LOG_FILE" return 1 else print_message $RED "应用启动失败,请检查日志文件: $LOG_FILE" rm -f "$PID_FILE" return 1 fi } # 显示应用状态 show_status() { local pid=$(get_app_pid) if [ -n "$pid" ]; then print_message $GREEN "应用正在运行" print_message $GREEN "PID: $pid" print_message $GREEN "端口: $PORT" if check_port $PORT; then print_message $GREEN "端口状态: 正在监听" else print_message $YELLOW "端口状态: 未监听" fi else print_message $YELLOW "应用未运行" fi } # 显示帮助信息 show_help() { echo "Java应用管理脚本" echo "" echo "使用方法:" echo " $0 [选项]" echo "" echo "选项:" echo " start 启动应用" echo " stop 停止应用" echo " restart 重启应用" echo " status 显示应用状态" echo " help 显示帮助信息" echo "" echo "配置:" echo " JAR包名称: $JAR_NAME" echo " 端口号: $PORT" echo "" echo "注意: 请确保在脚本开头正确配置 JAR_NAME 和 PORT 参数" } # ======================================== # 主程序 # ======================================== # 检查JAR文件是否存在 check_jar_exists # 处理命令行参数 case "${1:-restart}" in "start") start_app ;; "stop") stop_app ;; "restart") print_message $BLUE "重启应用..." stop_app if [ $? -eq 0 ]; then sleep 2 start_app else print_message $RED "停止应用失败,取消重启" exit 1 fi ;; "status") show_status ;; "help"|"-h"|"--help") show_help ;; *) print_message $RED "未知选项: $1" show_help exit 1 ;; esac