スクリプトの実行に失敗しました

スクリプトの実行に失敗しました

実行中の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

しかし、エラーは発生せず、ケースの説明に対する私のスクリプトは失敗します。${hoption}評価されていないと思います。

答え1

スクリプトの実行中はstdinから読み取ってはいけません。他hoptionのほとんどのプログラムと同様に、コマンドラインからオプションとして提供する必要があります。難しく聞こえますが、bashの組み込み機能を使用すると実際には非常に簡単です(要約は参考文献を参照)。rspidrspnamegetoptshelp 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}いることを確認してください。
また、各ケースにエコーを追加して、そのケースに到達したことを示します。

この場合、単一の文字だけを探しているので、次の方法で読み取りを使用します。

read -r -n 1 hoption

この-n 1フラグは、読み取りに新しい行ではなく1文字だけ待つように指示します。この-rフラグは特殊文字処理を無効にします。通常、そうしないでください-r明確な理由がない限り、常に使用する必要があります。そうしないと、奇妙な動作が発生する可能性があります。

私はスクリプトをテストしました。上記の方法で問題が解決しない場合、表示されるエラーメッセージは何ですか?

関連情報