萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux Java 服務通用啟動/停止/重啟腳本:自動偵測配置、記憶體調優、JMX/Debug 支援

企業級 Java 服務部署需標準化的啟動、停止、重啟腳本,支援:自動偵測專案目錄、讀取屬性檔、檢查埠口佔用、依記憶體大小調優 JVM 參數、支援 Debug/JMX 模式、輸出 PID 與標準輸出日誌。

目錄結構假設


/opt/myapp/
├── bin/
│   ├── start.sh
│   ├── stop.sh
│   └── restart.sh
├── conf/
│   └── server.properties   # server.name, server.netty.port
└── lib/
    └── *.jar

start.sh 核心邏輯


#!/bin/bash
cd `dirname $0`/..
DEPLOY_DIR=`pwd`
CONF_DIR=$DEPLOY_DIR/conf
SERVER_NAME=`sed '/server.name/!d;s/.*=//' conf/server.properties | tr -d '\r'`
SERVER_PORT=`sed '/server.netty.port/!d;s/.*=//' conf/server.properties | tr -d '\r'`

# 1. 檢查是否已啟動
PIDS=`ps --no-heading -C java -f --width 1000 | grep "$CONF_DIR" | awk '{print $2}'`
[ -n "$PIDS" ] && { echo "ERROR: $SERVER_NAME already started! PID: $PIDS"; exit 1; }

# 2. 檢查埠口佔用
[ -n "$SERVER_PORT" ] && {
  netstat -tln | grep -q ":$SERVER_PORT " && { echo "ERROR: Port $SERVER_PORT in use!"; exit 1; }
}

# 3. JVM 記憶體自動調優 (依實體記憶體)
BITS=`file $JAVA_HOME/bin/java | grep 64-bit`
if [ -n "$BITS" ]; then
  memTotal=`cat /proc/meminfo | grep MemTotal | awk '{printf "%d", $2/1024 }'`  # MB
  if [ $memTotal -gt 2500 ]; then
    JAVA_MEM_OPTS="-server -Xmx1024m -Xms1024m -Xmn400m -XX:PermSize=128m -XX:+UseConcMarkSweepGC ..."
  else
    JAVA_MEM_OPTS="-server -Xmx1024m -Xms1024m -Xmn400m -XX:PermSize=128m -XX:+UseConcMarkSweepGC ..."
  fi
else
  JAVA_MEM_OPTS="-server -Xmx1024m -Xms1024m -XX:PermSize=128m -XX:+UseParallelGC"
fi

# 4. Debug / JMX 參數
[ "$1" = "debug" ] && JAVA_DEBUG_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"
[ "$1" = "jmx" ]   && JAVA_JMX_OPTS="-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

# 5. 啟動
nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -classpath $CONF_DIR:$LIB_JARS com.example.Main > $LOGS_DIR/stdout.log 2>&1 &

# 6. 等待啟動完成 (輪詢 PID)
COUNT=0
while [ $COUNT -lt 1 ]; do sleep 1; COUNT=`ps --no-heading -C java -f --width 1000 | grep "$DEPLOY_DIR" | awk '{print $2}' | wc -l`; done
echo "OK! PID: $PIDS"

stop.sh 優雅關閉


#!/bin/bash
cd `dirname $0`/..
DEPLOY_DIR=`pwd`
PIDS=`ps --no-heading -C java -f --width 1000 | grep "$DEPLOY_DIR" | awk '{print $2}'`
[ -z "$PIDS" ] && { echo "Not running"; exit 1; }

[ "$1" != "skip" ] && ./dump.sh  # 可選:觸發 heap dump / thread dump

for PID in $PIDS; do kill $PID; done
# 等待進程結束
while ps -p $PID > /dev/null 2>&1; do sleep 1; done
echo "Stopped. PID: $PIDS"

restart.sh


#!/bin/bash
cd `dirname $0`
./stop.sh
./start.sh

生產環境強化建議

  • 使用 systemd 服務單元管理,替代手寫腳本:
    Type=simple, ExecStart=/opt/myapp/bin/start.sh, ExecStop=/opt/myapp/bin/stop.sh, Restart=on-failure。
  • JVM 參數外部化至 conf/jvm.options,版本控管並支援環境變數覆寫。
  • 啟用 GC 日誌:-Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime,level,tags:filecount=5,filesize=100m (Java 9+)。
  • 健康檢查端點 (/actuator/health) 搭配 systemd WatchdogSec 或 Kubernetes liveness probe。
copyright © 萬盛學電腦網 all rights reserved