在 Linux 環境下,Java 後台應用若無防護,可被重複啟動導致資源浪費、端口衝突、資料競爭。本文提供一個健壯的啟動腳本,透過 ps + grep + awk 檢測進程是否存在,實現「單實例守護」功能,並處理腳本權限、編碼格式等常見坑點。
app/
├── bin/ # 啟動腳本 startup.sh、類別檔、配置檔
└── lib/ # 依賴 JAR 包
主類:mypack.MyAppMain
#!/bin/sh
programdir="."
program="mypack.MyAppMain"
num=$#
temp=$CLASSPATH
# 設定 lib 目錄所有 JAR 到 CLASSPATH
libs=../lib/*
append() { temp=$temp":"$1; }
for file in $libs; do append $file; done
export CLASSPATH=$temp:.:../:$programdir
export LANG=zh_CN
# 核心:檢測進程是否已存在
res=`ps aux | grep java | grep $program | grep -v grep | awk '{print $2}'`
if [ -n "$res" ]; then
echo "MyAppMain already running"
else
# 後台啟動,輸出重定向到 nohup.out
nohup java -classpath $CLASSPATH mypack.MyAppMain &
sleep 3 # 等待 JVM 啟動
unset res
# 二次驗證啟動成功
res=`ps aux | grep java | grep $program | grep -v grep | awk '{print $2}'`
if [ -n "$res" ]; then
echo "MyAppMain start success"
else
echo "MyAppMain start error"
fi
fi
ps aux 列出所有進程 → grep java 過濾 Java 進程 → grep $program 精確匹配主類名 → grep -v grep 排除 grep 自身 → awk '{print $2}' 取得 PID。sleep 3 再檢查確認 JVM 確實掛起(防止啟動即崩潰)。../lib/* 所有 JAR,避免手動維護列表。nohup.out。| 問題 | 現象 | 解決 |
|---|---|---|
| 腳本無執行權限 | Permission denied | chmod 755 startup.sh (或 777) |
| 編碼格式錯誤 | : bad interpreter: No such file or directory | 確保檔案格式為 Unix (LF),非 Windows (CRLF);用 dos2unix startup.sh 或編輯器轉換 |
| grep 匹配過寬 | 誤殺無關進程 | 主類名需足夠唯一,或加上完整包名 mypack.MyAppMain |
| CLASSPATH 為空 | 找不到主類 | 腳本先組裝 ../lib/* 再導出 |