実行中の 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
hoption
スクリプトの実行中に 、 、rspid
を標準入力から読み取る代わりにrspname
、他のほとんどのプログラムと同様に、それらをコマンドラインのオプションとして受け取る必要があります。これは難しそうに聞こえますが、実際には bash 組み込み関数を使用すると非常に簡単ですgetopts
(help getopts
概要については を参照してください)。
こうすることで、シェルのコマンドライン履歴を使用するだけで、同じ引数でスクリプトを簡単にテストできます (つまり、同じ値を何度も入力する必要はありません)。さらに重要なことに、適切な引数で呼び出すだけで、このスクリプトを他のスクリプトで簡単に使用できます。
これはそれを実行するバージョンです(いくつかの小さな改善と変数の引用の修正 - 毎回使用済み変数なので、二重引用符で囲みましたか? あなたもそうすべきです。
#! /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}
正しく設定されていることを確認するために、読み込んだ後にデバッグ行を追加します。
また、各ケースに到達したことを示す echo を各ケースに追加します。
この場合は 1 文字だけを探しているので、次のように read を使用します。
read -r -n 1 hoption
この-n 1
フラグは、read に 1 文字だけ待機し、新しい行を待機しないように指示します。この-r
フラグは特殊文字の処理を無効にします。一般的に、使用しない明確な理由がない限り、常に使用する必要があります-r
。そうしないと、異常な動作が発生する可能性があります。
スクリプトをテストしたところ、少なくとも私の環境では (変更なしで) hoption の値を取得しているようです。上記で問題が解決しない場合は、どのようなエラー メッセージが表示されていますか?