暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

基于阿里千问实现通过shell监控FullGC告警并自动重启

济南小老虎 2025-02-22
10

背景

最近想进行一下内存OOM测试验证的工作.
但是出现oom再去抓取的时候可能已经晚了. 
所以想通过脚本的方式进行定期验证
当连续出现FullGC自动抓取部分内容.
并且可以进行邮件告警.后者是重启服务


工具

前几天发现通过阿里千问 可以快速写SQL
想着shell 脚本也是如此. 
能够减少自己的繁重工作量.
减少掉头发
所以进行相关的工作处理. 


提问prompt

通过shell 脚本判断一个文件内 
5min内出现两次Full GC 时进行告警 
可以进行重启或者是 其他操作

其实建议是重启, 如果是不同的fullGC 进行 dump的话 磁盘会慢
对于测试环境来说 喝杯茶 重启一遍 也挺好 -_- 


脚本提示后优化后的SQL

#!/bin/bash
while true ; do
# 需要监控的文件路径
LOG_FILE="/root/gc.log"

# 遍历日志文件中的每一行
count=$(
while IFS= read -r line; do
    GCcount=0
# 提取日期时间部分,并去掉毫秒和时区信息
    DATE_TIME=$(echo "$line"  |grep "Full GC" | grep -oP '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}')
    # 跳过无法匹配日期时间格式的行
    if [ -z "$DATE_TIME" ]; then
        continue
    fi
    # 将提取出的日期时间转换为Unix时间戳
    TIME_STAMP=$(date -d "${DATE_TIME}" +%s)
    MIN2=$(date -d "5 minutes ago" +%s)
    #echo "$MIN2"
    # 输出结果
    if [ $TIME_STAMP -gt  $MIN2 ]; then
      echo "原始日志时间: ${DATE_TIME}, 转换后的时间戳: $TIME_STAMP"
    fi
done < "$LOG_FILE" |wc -l )
success=`lsof -i:5200 |wc -l`
if [ $success -lt 1 ]; then
echo "启动不成功自动进入下一次"
sleep 20
continue
fi
echo $count
if [ $count -gt 1 ]; then
  echo "出现问题, 可以抓取分析"
  deploy/mailoom # 先发邮件, 再自动抓相关信息
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` Thread.print > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.jstack.log
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` GC.class_histogram > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.gc.log
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` VM.native_memory > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.nmt.log
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` GC.heap_dump root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.heap.dump
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` Thread.print > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.jstack.log
  sleep 60
  ps -ef |grep java |grep caf  |awk '{print $2}' |xargs kill -9
  cd /myapp/
  ./startup.sh
  sleep 600
fi
sleep 20
done
# 输出结果


脚本分析-GC次数判定

count=$(
while IFS= read -r line; do
    GCcount=0
# 提取日期时间部分,并去掉毫秒和时区信息
    DATE_TIME=$(echo "$line"  |grep "Full GC" | grep -oP '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}')
    # 跳过无法匹配日期时间格式的行
    if [ -z "$DATE_TIME" ]; then
        continue
    fi
    # 将提取出的日期时间转换为Unix时间戳
    TIME_STAMP=$(date -d "${DATE_TIME}" +%s)
    MIN2=$(date -d "5 minutes ago" +%s)
    #echo "$MIN2"
    # 输出结果
    if [ $TIME_STAMP -gt  $MIN2 ]; then
      echo "原始日志时间: ${DATE_TIME}, 转换后的时间戳: $TIME_STAMP"
    fi
done < "$LOG_FILE" |wc -l )


脚本分析-GC次数判定

其实这个脚本不太合理
因为每次循环 都要读取整个文件. 
理论上只需要读最后面的多少行就可以了.  

AI给出来的整体算法性能 其实很差, 并不是最优解. 
但是基于GClog的时间格式进行时间戳大小比较的想法比较简洁. 

这一点自己写起来 的确麻烦. 用正则进行匹配 .然后转换. 虽然算法性能垃圾
但是可用. 


脚本分析-判断服务是否成功

success=`lsof -i:5200 |wc -l`
if [ $success -lt 1 ]; then
echo "启动不成功自动进入下一次"
sleep 20
continue
fi

没20秒判断一次, 如果服务启动失败了, 那么就重新While 的虚幻. 


脚本分析-抓取和告警

if [ $count -gt 1 ]; then
  echo "出现问题, 可以抓取分析"
  deploy/mailoom # 先发邮件, 再自动抓相关信息
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` Thread.print > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.jstack.log
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` GC.class_histogram > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.gc.log
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` VM.native_memory > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.nmt.log
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` GC.heap_dump root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.heap.dump
  jcmd `ps -ef |grep java |grep caf  |awk '{print $2}'` Thread.print > root/`ps -ef |grep java |grep caf |awk '{print $2}'`_`date "+%Y%m%d%H%M%S"`.jstack.log
  sleep 60
  ps -ef |grep java |grep caf  |awk '{print $2}' |xargs kill -9
  cd /myapp/
  ./startup.sh
  sleep 600
fi
sleep 20
done

5min内连续出现两次fullGC 就抓取然后重启. 
然后继续进行循环
每20秒检查一下当前的gclog. 


邮件告警

编写shell 发送邮件 
通过yum install mailx 进行处理

修改 /etc/mail.rc 进行邮件认证设置

export  PATH=$PATH:/usr/sbin/
echo `date +%Y%m%d%H%M`_2FullGC_In_5min|mail -s "139.227_Warning_FullGC_Occur,`date +%Y%m%d%H%M`"  mail@mail.com


文章转载自济南小老虎,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论