整了个脚本,希望以后cpu高的时候,能够一键定位~~~~

郑重声明:参数要根据自身业务调整,线上执行jstack 要谨慎,本文只提供demo, 不作为线上操作标准。由于操作失误产生的后果由使用方自己完全负责哈~~~

1 用法:
(1)scmp 登录机器
(2)创建getCpuUsageOfJavaThread.sh 文件。

  1. vi getCpuUsageOfJavaThread.sh

(3) 将如下代码copy进 getCpuUsageOfJavaThread.sh

  1. #!/bin/bash
  2. echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~welcom~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  3. echo "usage: sh getCpuUsageOfJavaThread.sh sleepTime execCount cpuUsageThreshold"
  4. 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"
  5. echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~gogogo~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  6. sleepTime=$1
  7. execCount=$2
  8. cpuUsageThreshold=$3
  9. if [ ! -n "$1" ] ;then
  10. echo "param sleepTime is null"
  11. 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"
  12. exit
  13. fi
  14. if [ ! -n "$2" ] ;then
  15. echo "param execCount is null"
  16. 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"
  17. exit
  18. fi
  19. if [ ! -n "$3" ] ;then
  20. echo "param cpuUsageThreshold is null"
  21. 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"
  22. exit
  23. fi
  24. if [ ! -d "cpuData" ]; then
  25. mkdir cpuData
  26. fi
  27. cd cpuData
  28. n=0
  29. while (($n<$execCount))
  30. do
  31. #获取cpu使用大于sleepTime% 的 java 线程:
  32. now=$(date "+%Y%m%d-%H%M%S")
  33. mkdir ${now}
  34. cd ${now}
  35. 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}
  36. awk '{print $2,$3}' ${now}_threadCpuGT${cpuUsageThreshold} > ${now}_threadId
  37. jstack ${javapid} > ${now}_fullstackInfo
  38. while read tid_cpu;
  39. do
  40. # 将线程转换为十六进制
  41. tid=`echo $tid_cpu | awk '{print $1}'`
  42. cpu=`echo $tid_cpu | awk '{print $2}'`
  43. threadId16=$(printf "0x%x\n" ${tid})
  44. echo "================= 线程id为 threadId-${tid}, 对应十六进制为 ${threadId16} , cpu使用率为 ${cpu} %. 详细堆栈信息如下 :=================" >> ${now}_final_result
  45. #grep -A 30 "nid="${threadId16}" " ${now}_fullstackInfo >> ${now}_final_result
  46. sed -n -e "/nid=${threadId16} /, /^$/ p" ${now}_fullstackInfo >> ${now}_final_result
  47. done < ${now}_threadId
  48. rm ${now}_threadCpuGT${cpuUsageThreshold}
  49. rm ${now}_threadId
  50. #执行次数加一
  51. n=$((n+1))
  52. echo "=========execute ${n} times========="
  53. # sleep 几秒
  54. sleep $sleepTime
  55. # 跳出一层,方便执行下一次
  56. cd ..
  57. done
  58. echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ have a good time, bye ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"

(4)执行如下指令:

郑重声明:参数要根据自身业务调整,线上执行jstack 要谨慎,本文只提供demo, 不作为线上操作标准。由于操作失误产生的后果由使用方自己完全负责哈~~~

demo :

  1. sh getCpuUsageOfJavaThread.sh 20 5 1

表示: 每20秒执行一次 ps 跟 jstack , 总共执行5次,会选择cpu 使用大于1% 的线程进行进行输出。

(5)结果文件说明:
文件夹路径: cd cpuData/xxxxxx-yy (相对于getCpuUsageOfJavaThread.sh 文件所在的目录)

  1. 20201204-062028_final_result 展示线程,以及对应的cpu使用率 的最终结果文件。
  2. 20200303-172806_fullstackInfo jstack 完全堆栈信息

图片示例:
image.png

结果实例:
image.png