整了个脚本,希望以后cpu高的时候,能够一键定位~~~~
郑重声明:参数要根据自身业务调整,线上执行jstack 要谨慎,本文只提供demo, 不作为线上操作标准。由于操作失误产生的后果由使用方自己完全负责哈~~~
1 用法:
(1)scmp 登录机器
(2)创建getCpuUsageOfJavaThread.sh 文件。
vi getCpuUsageOfJavaThread.sh
(3) 将如下代码copy进 getCpuUsageOfJavaThread.sh
#!/bin/bash
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~welcom~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "usage: sh getCpuUsageOfJavaThread.sh sleepTime execCount cpuUsageThreshold"
echo "eg: sh getCpuUsageOfJavaThread.sh 20 5 1 -- every 20s execute jstack once, and all execute 5 times . if cpu usage bigger than 1% while print"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~gogogo~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
sleepTime=$1
execCount=$2
cpuUsageThreshold=$3
if [ ! -n "$1" ] ;then
echo "param sleepTime is null"
echo "eg: sh getCpuUsageOfJavaThread.sh 20 5 1 -- every 20s execute jstack, and execute 5 times all. if cpu usage bigger than 1% while print"
exit
fi
if [ ! -n "$2" ] ;then
echo "param execCount is null"
echo "eg: sh getCpuUsageOfJavaThread.sh 20 5 1 -- every 20s execute jstack, and execute 5 times all. if cpu usage bigger than 1% while print"
exit
fi
if [ ! -n "$3" ] ;then
echo "param cpuUsageThreshold is null"
echo "eg: sh getCpuUsageOfJavaThread.sh 20 5 1 -- every 20s execute jstack, and execute 5 times all. if cpu usage bigger than 1% while print"
exit
fi
if [ ! -d "cpuData" ]; then
mkdir cpuData
fi
cd cpuData
n=0
while (($n<$execCount))
do
#获取cpu使用大于sleepTime% 的 java 线程:
now=$(date "+%Y%m%d-%H%M%S")
mkdir ${now}
cd ${now}
javapid=$(jps | grep "jar" | awk '{print $1}')&&ps H -e -o pid,tid,pcpu,args --sort=-pcpu | awk -v jpid="$javapid" -v cpuUsageThreshold="$cpuUsageThreshold" '{if ($1 == jpid && $3 > cpuUsageThreshold) print $0}' > ${now}_threadCpuGT${cpuUsageThreshold}
awk '{print $2,$3}' ${now}_threadCpuGT${cpuUsageThreshold} > ${now}_threadId
jstack ${javapid} > ${now}_fullstackInfo
while read tid_cpu;
do
# 将线程转换为十六进制
tid=`echo $tid_cpu | awk '{print $1}'`
cpu=`echo $tid_cpu | awk '{print $2}'`
threadId16=$(printf "0x%x\n" ${tid})
echo "================= 线程id为 threadId-${tid}, 对应十六进制为 ${threadId16} , cpu使用率为 ${cpu} %. 详细堆栈信息如下 :=================" >> ${now}_final_result
#grep -A 30 "nid="${threadId16}" " ${now}_fullstackInfo >> ${now}_final_result
sed -n -e "/nid=${threadId16} /, /^$/ p" ${now}_fullstackInfo >> ${now}_final_result
done < ${now}_threadId
rm ${now}_threadCpuGT${cpuUsageThreshold}
rm ${now}_threadId
#执行次数加一
n=$((n+1))
echo "=========execute ${n} times========="
# sleep 几秒
sleep $sleepTime
# 跳出一层,方便执行下一次
cd ..
done
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ have a good time, bye ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(4)执行如下指令:
郑重声明:参数要根据自身业务调整,线上执行jstack 要谨慎,本文只提供demo, 不作为线上操作标准。由于操作失误产生的后果由使用方自己完全负责哈~~~
demo :
sh getCpuUsageOfJavaThread.sh 20 5 1
表示: 每20秒执行一次 ps 跟 jstack , 总共执行5次,会选择cpu 使用大于1% 的线程进行进行输出。
(5)结果文件说明:
文件夹路径: cd cpuData/xxxxxx-yy (相对于getCpuUsageOfJavaThread.sh 文件所在的目录)
20201204-062028_final_result 为 展示线程,以及对应的cpu使用率 的最终结果文件。
20200303-172806_fullstackInfo jstack 完全堆栈信息
图片示例:
结果实例: