Die Skriptausführung ist fehlgeschlagen

Die Skriptausführung ist fehlgeschlagen

Ich habe ein Skript erstellt, um den Heap- und Thread-Dump eines laufenden Java-Prozesses zu erfassen.

#! /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

Aber mein Skript schlägt bei der Case-Anweisung fehl, ohne dass ein Fehler ausgegeben wird. Ich glaube, ${hoption}es wird nicht ausgewertet.

Antwort1

Anstatt hoption, rspidund rspnamevon stdin zu lesen, während das Skript ausgeführt wird, sollten Sie sie als Optionen in der Befehlszeile verwenden, so wie es die meisten anderen Programme tun. Das klingt schwierig, ist aber eigentlich ganz einfach, wenn man das in bash integrierte Programm verwendet getopts(siehe help getoptsfür eine Zusammenfassung).

Auf diese Weise können Sie Ihr Skript einfach mit denselben Argumenten testen, indem Sie einfach den Befehlszeilenverlauf Ihrer Shell verwenden (d. h. Sie müssen NICHT immer wieder dieselben Werte eingeben) und, was noch wichtiger ist, Sie können dieses Skript einfach in anderen Skripten verwenden, indem Sie es einfach mit den richtigen Argumenten aufrufen.

Hier ist eine Version, die das tut (plus ein paar kleinere Verbesserungen. Und Korrekturen an der Variablenanführung - beachten Sie, wie jedes Mal, wenn ichgebrauchteine Variable, ich habe sie in Anführungszeichen gesetzt? Das sollten Sie auch tun.)

#! /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

Antwort2

echo ${hoption}Fügen Sie nach dem Einlesen eine Debugzeile hinzu, um zu bestätigen, dass es richtig eingestellt wurde.
Fügen Sie außerdem in jedem Fall ein Echo ein, das anzeigt, dass Sie diesen Fall erreicht haben.

In diesem Fall würde ich read folgendermaßen verwenden, da Sie nur nach einem einzelnen Zeichen suchen:

read -r -n 1 hoption

Das -n 1Flag weist read an, nur auf 1 Zeichen und nicht auf eine neue Zeile zu warten. Das -rFlag deaktiviert die Behandlung von Sonderzeichen. Generell sollten Sie es immer verwenden, -res sei denn, Sie haben einen expliziten Grund, es nicht zu tun – sonst kann es zu merkwürdigem Verhalten kommen.

Ich habe das Skript getestet und es scheint den Wert von hoption zu erhalten, zumindest in meiner Umgebung (ohne Änderungen). Wenn das oben genannte Ihr Problem nicht behebt, welche Fehlermeldung erhalten Sie?

verwandte Informationen