背景
最近想进行一下内存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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。