#!/bin/bash# @Function# Find out the highest cpu consumed threads of java, and print the stack of these threads.## @Usage# $ ./show-busy-java-threads.sh## @author Jerry Leereadonly PROG=`basename $0`readonly -a COMMAND_LINE=("$0""$@")
usage(){cat<<EOF
Usage: ${PROG} [OPTION]...
Find out the highest cpu consumed threads of java, and print the stack of these threads.
Example: ${PROG} -c 10
Options:
-p, --pid find out the highest cpu consumed threads from the specifed java process,
default from all java process.
-c, --count set the thread count to show, default is 5
-h, --help display this help and exit
EOFexit$1}readonly ARGS=`getopt -n "$PROG" -a -o c:p:h -l count:,pid:,help -- "$@"`[$? -ne 0 ]&& usage 1
evalset -- "${ARGS}"whiletrue;docase"$1"in
-c|--count)
count="$2"shift 2
;;
-p|--pid)
pid="$2"shift 2
;;
-h|--help)
usage
;;
--)shiftbreak;;
esac
done
count=${count:-5}
redEcho(){[ -c /dev/stdout ]&&{# if stdout is console, turn on color output.echo -ne "\033[1;31m"echo -n "$@"echo -e "\033[0m"}||echo"$@"}
yellowEcho(){[ -c /dev/stdout ]&&{# if stdout is console, turn on color output.echo -ne "\033[1;33m"echo -n "$@"echo -e "\033[0m"}||echo"$@"}
blueEcho(){[ -c /dev/stdout ]&&{# if stdout is console, turn on color output.echo -ne "\033[1;36m"echo -n "$@"echo -e "\033[0m"}||echo"$@"}# Check the existence of jstack command!if!which jstack &> /dev/null;then[ -z "$JAVA_HOME"]&&{
redEcho "Error: jstack not found on PATH!"exit 1
}![ -f "$JAVA_HOME/bin/jstack"]&&{
redEcho "Error: jstack not found on PATH and $JAVA_HOME/bin/jstack file does NOT exists!"exit 1
}![ -x "$JAVA_HOME/bin/jstack"]&&{
redEcho "Error: jstack not found on PATH and $JAVA_HOME/bin/jstack is NOT executalbe!"exit 1
}export PATH="$JAVA_HOME/bin:$PATH"fireadonly uuid=`date +%s`_${RANDOM}_$$
cleanupWhenExit(){rm /tmp/${uuid}_* &> /dev/null
}trap"cleanupWhenExit" EXIT
printStackOfThread(){
local line
local count=1
while IFS=" "read -a line ;do
local pid=${line[0]}
local threadId=${line[1]}
local threadId0x=`printf %x ${threadId}`
local user=${line[2]}
local pcpu=${line[4]}
local jstackFile=/tmp/${uuid}_${pid}[! -f "${jstackFile}"]&&{{if["${user}"=="${USER}"];then
jstack ${pid}>${jstackFile}elseif[$UID== 0 ];thensudo -u ${user} jstack ${pid}>${jstackFile}else
redEcho "[$((count++))] Fail to jstack Busy(${pcpu}%) thread(${threadId}/0x${threadId0x}) stack of java process(${pid}) under user(${user})."
redEcho "User of java process($user) is not current user($USER), need sudo to run again:"
yellowEcho " sudo ${COMMAND_LINE[@]}"echocontinuefifi}||{
redEcho "[$((count++))] Fail to jstack Busy(${pcpu}%) thread(${threadId}/0x${threadId0x}) stack of java process(${pid}) under user(${user})."echorm${jstackFile}continue}}
blueEcho "[$((count++))] Busy(${pcpu}%) thread(${threadId}/0x${threadId0x}) stack of java process(${pid}) under user(${user}):"sed"/nid=0x${threadId0x} /,/^$/p" -n ${jstackFile}done}ps -Leo pid,lwp,user,comm,pcpu --no-headers |{[ -z "${pid}"]&&awk'$4=="java"{print $0}'||awk -v "pid=${pid}"'$1==pid,$4=="java"{print $0}'}|sort -k5 -r -n |head --lines "${count}"| printStackOfThread