企業級 Java 服務部署需標準化的啟動、停止、重啟腳本,支援:自動偵測專案目錄、讀取屬性檔、檢查埠口佔用、依記憶體大小調優 JVM 參數、支援 Debug/JMX 模式、輸出 PID 與標準輸出日誌。
/opt/myapp/
├── bin/
│ ├── start.sh
│ ├── stop.sh
│ └── restart.sh
├── conf/
│ └── server.properties # server.name, server.netty.port
└── lib/
└── *.jar
#!/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"
#!/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"
#!/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。conf/jvm.options,版本控管並支援環境變數覆寫。-Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime,level,tags:filecount=5,filesize=100m (Java 9+)。WatchdogSec 或 Kubernetes liveness probe。