我創建了一個腳本來捕獲正在運行的 java 進程的堆和線程轉儲。
#! /bin/bash
myhost=$(uname)
if [ "${myhost}" == "SunOS" ]; then
HEAPLOGS="/export/home/${USER}/applog/heapdump"
THREADLOGS="/export/home/${USER}/applog/threaddump"
elif [ "${myhost}" == "Linux" ]; then
HEAPLOGS="/opt/app/${USER}/applog/heapdump"
THREADLOGS="/opt/app/${USER}/applog/threaddump"
fi
DAY=$(date +%Y.%m.%d)
NOW=$(date +%Y.%m.%d-%H.%M.%S)
EXPIRE=30
echo " Please select your option "
echo
echo " Heap-Dump : 0 "
echo " Thread-Dump : 1 "
echo " Both of above : 2 "
read hoption
echo
echo " Enter PID :"
read rspid
echo " Enter InstanceName :"
read rspname
case ${hoption} in
0)
# generate java heapdump
jmap -dump:format=b,file=${HEAPLOGS}/${rspname}-${NOW}.hprof ${rspid}"
chmod 644 ${HEAPLOGS}/${rspname}-${NOW}.hprof
;;
1)
# generate java threaddump
jstack ${rspid} > ${THREADLOGS}/${rspname}-${NOW}.log"
chmod 644 ${THREADLOGS}/${rspname}-${NOW}.log
;;
2)
# generate java heapdump
jmap -dump:format=b,file=${HEAPLOGS}/${rspname}-${NOW}.hprof ${rspid}"
chmod 644 ${HEAPLOGS}/${rspname}-${NOW}.hprof
# generate java threaddump
jstack ${rspid} > ${THREADLOGS}/${rspname}-${NOW}.log"
chmod 644 ${THREADLOGS}/${rspname}-${NOW}.log
;;
esac
但我的腳本對於 case 語句失敗,沒有拋出任何錯誤。我相信${hoption}
沒有得到評估。
答案1
您不應在腳本運行時從 stdin 讀取hoption
,rspid
和rspname
,而是應將它們作為命令行上的選項,就像大多數其他程式一樣。這聽起來很困難,但實際上使用 bash 內建指令非常容易getopts
(請參閱help getopts
參考資料 中的摘要)
這樣,您只需使用shell 的命令列歷史記錄即可輕鬆使用相同的參數測試您的腳本(即不必一次又一次地輸入相同的值),更重要的是,您可以輕鬆地在其他腳本中使用此腳本,只需使用正確的參數呼叫它即可。
這是一個可以做到這一點的版本(加上一些小的改進。並修復了變數引用 - 請注意每次我如何用過的一個變量,我把它用雙引號引起來了?你也應該這樣做。
#! /bin/bash
case "$(uname)" in
Linux) APPPATH='/opt/app/' ;;
SunOS) APPPATH='/export/home/' ;;
*) echo "Unknown OS" >/dev/stderr ; exit 1 ;;
esac
HEAPLOGS="$APPPATH/${USER}/applog/heapdump"
THREADLOGS="$APPPATH/${USER}/applog/threaddump"
DAY=$(date +%Y.%m.%d)
NOW=$(date +%Y.%m.%d-%H.%M.%S)
EXPIRE=30
usage() {
[ -z "$*" ] || printf "%s\n\n" "$@"
cat <<__EOF__
Usage: $0 <-h|-t|-b> -e <expire> -p <pid> -i <instance>
-h Heap-Dump
-t Thread-Dump
-b Both of above
-e Expiry time (defaults to 30)
-p PID
-i Instance Name
__EOF__
exit 1
}
unset hoption rspid rspname
# process command line options
while getopts 'htbe:p:i:' opt ; do
case "$opt" in
h|t|b) [ -z "$hoption" ] && hoption="$opt" || \
usage "Only use one of -h, -t, or -b"
;;
e) EXPIRE="$OPTARG" ;;
p) rspid="$OPTARG" ;;
i) rspname="$OPTARG" ;;
*) usage ;;
esac
done
[ -z "$hoption" ] && usage "Must provide one of -h, -t, or -b"
[ -z "$rspid" ] && usage "'-p <PID>' is required"
[ -z "$rspname" ] && usage "'-i <instance>' is required"
case "$hoption" in
h) # generate java heapdump
jmap -dump:format=b,file="${HEAPLOGS}/${rspname}-${NOW}.hprof" "${rspid}"
chmod 644 "${HEAPLOGS}/${rspname}-${NOW}.hprof"
;;
t) # generate java threaddump
jstack "${rspid}" > "${THREADLOGS}/${rspname}-${NOW}.log"
chmod 644 "${THREADLOGS}/${rspname}-${NOW}.log"
;;
b) # generate java heapdump
jmap -dump:format=b,file="${HEAPLOGS}/${rspname}-${NOW}.hprof" "${rspid}"
chmod 644 "${HEAPLOGS}/${rspname}-${NOW}.hprof"
# generate java threaddump
jstack "${rspid}" > "${THREADLOGS}/${rspname}-${NOW}.log"
chmod 644 "${THREADLOGS}/${rspname}-${NOW}.log"
;;
esac
答案2
在讀入後新增調試行echo ${hoption}
以確認其設定正確。
還要在每種情況下添加一個回顯,表示您已到達該情況。
在這種情況下,由於您只查找單個字符,因此我會以這種方式使用 read :
read -r -n 1 hoption
該-n 1
標誌告訴 read 僅等待 1 個字元而不等待新行。此-r
標誌禁用特殊字元處理。一般來說,-r
除非您有明確的理由不這樣做,否則您應該始終使用 - 否則可能會導致奇怪的行為。
我測試了該腳本,它似乎確實獲得了 hoption 的值,至少在我的環境中(沒有任何更改)。如果上述內容無法解決您的問題,您收到的錯誤訊息是什麼?