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
, rspid
und rspname
von 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 getopts
fü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 1
Flag weist read an, nur auf 1 Zeichen und nicht auf eine neue Zeile zu warten. Das -r
Flag deaktiviert die Behandlung von Sonderzeichen. Generell sollten Sie es immer verwenden, -r
es 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?