Eu criei um script para capturar o despejo de heap e thread de um processo Java em execução.
#! /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
Mas meu script falha na declaração de caso sem gerar nenhum erro. Acredito ${hoption}
que não esteja sendo avaliado.
Responder1
Em vez de ler hoption
e rspid
de rspname
stdin enquanto o script está em execução, você deve considerá-los como opções na linha de comando, assim como a maioria dos outros programas faz. Isso parece difícil, mas na verdade é bastante fácil usando o bash-builtin getopts
(veja help getopts
um resumo)
Dessa forma, você pode testar facilmente seu script com os mesmos argumentos apenas usando o histórico de linha de comando do seu shell (ou seja, NÃO precisa digitar os mesmos valores repetidamente) e, mais importante, você pode usar facilmente esse script em outros scripts, apenas chamando-o com os argumentos certos.
Aqui está uma versão que faz isso (além de algumas pequenas melhorias. E correções para a cotação de variáveis - observe como toda vez que euusadouma variável, coloquei-a entre aspas duplas? Você deveria também.)
#! /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
Responder2
Adicione uma linha de depuração echo ${hoption}
depois de lê-la para confirmar que está sendo definida corretamente.
Coloque também um eco em cada caso indicando que você chegou a esse caso.
Nesse caso, como você está procurando apenas um único caractere, eu usaria read desta forma:
read -r -n 1 hoption
O -n 1
sinalizador diz ao read para esperar apenas 1 caractere e não esperar por uma nova linha. o -r
sinalizador desativa o tratamento especial de caracteres. Em geral, você deve sempre usar, -r
a menos que tenha uma razão explícita para não fazê-lo - caso contrário, um comportamento estranho pode resultar.
Testei o script e parece estar obtendo o valor de hoption, pelo menos no meu ambiente (sem nenhuma alteração). Se o procedimento acima não resolver o seu problema, qual é a mensagem de erro que você está recebendo?