提取mysql慢sql的shell脚本,适合crontab使用
源码:
#!/bin/bash
#
# Mysql slow 分析脚本
# Operating System: CentOS Linux 7 (Core)
# Date: 20220830
#
Version="0.1"
init()
{
#环境变量
source /etc/profile
export PATH=${PATH}:/usr/sbin
#脚本所在目录
SHELL_FOLDER=$(dirname $(readlink -f "$0"))
#慢sql文件
slowLogFile="/hkdata/mysql/slow.log"
#是否告警
IS_alert="1"
#邮箱地址
Mail=""
#本机IP地址
Ip_Addr="`ip a s | grep global | grep -v "192.168" | awk '{print $2}' | head -n 1 | cut -d "/" -f 1`"
#慢SQL秒,大于等于
sec="5"
}
main()
{
#判断日志文件是否存在
if ! test -f $slowLogFile; then
echo "$slowLogFile 日志文件不存在!"
exit 0
fi
#获取文本内部开始时间(第一次运行时默认从上次记录文本里取,如果没有默认查找slow最后行的)
if test -f startDATE.txt; then
startDATE="$(cat ${SHELL_FOLDER}/startDATE.txt)" #开始时间(当分隔符),如果不存在也没事
else
:
fi
endDATE="$(tail -n 1024 ${slowLogFile} | grep "# Time:" | tail -n1 | cut -d "+" -f 1)" #结束时间(当分隔符)
if test "$endDATE" = ""; then #如果为空增大查找范围
endDATE="$(tail -n 4096 ${slowLogFile} | grep "# Time:" | tail -n1 | cut -d "+" -f 1)"
fi
if test "$endDATE" != ""; then #下一次运行充当开始时间的分隔符
echo $endDATE > startDATE.txt
fi
#startDATE="Time: 2022-08-30T10:22:35.455603" #测试
#endDATE="# Time: 2022-08-30T10:26:15.097185" #测试
if test "$startDATE" != "$endDATE"; then
awk '/'"${startDATE}"'/,/'"${endDATE}"'/{if(i>=1)print x; x=$0; i++}' ${slowLogFile} > ${SHELL_FOLDER}/newSlow.txt #正则匹配,输出 "# Time: 2022-08-19T16:54:45.849179"行 至 "# Time: 2022-08-19T16:54:45.849179"行 到newSlow.txt文件
echo $endDATE >> ${SHELL_FOLDER}/newSlow.txt
cat ${SHELL_FOLDER}/newSlow.txt | while read line; do #判断输出文件的否合格(可与忽略)
result=$(echo $line | grep "# Time: ")
if [[ "$result" != "" ]]; then
echo $line >> $SHELL_FOLDER/temp.txt
else
echo $line >> $SHELL_FOLDER/temp.txt
fi
done
else
echo "文本没有变化!没有新日志产生"
exit 0 #开始时间等于结束时间时,slow.log文件没有更新。退出
fi
}
Split_text()
{
TArray=(`awk '/Time:/,/Time:/{print}' $SHELL_FOLDER/temp.txt | cut -d "+" -f 1 | awk '{print $3}'`) #从$SHELL_FOLDER/temp.txt 文件中找"时间",并存储在数组中当分割符。(目的是分割每一个慢sql)
echo ${TArray[0]}
for((i=0; i<${#TArray[@]}; i++)) #遍历数组
do
echo "$i"
let t=i #i作为数组下标
let t=t+1 #t作为下一个数组下标
awk '/'"${TArray[i]}"'/,/'"${TArray[t]}"'/{if(i>=1)print x; x=$0; i++}' ${slowLogFile} > ${SHELL_FOLDER}/3.txt #分割好的每个sql信息存储在3.txt
Time="`grep Query_time 3.txt | awk '{print $3}' | cut -d "." -f 1`" #查找3.txt的Query_time值
echo "慢SQL时间: ${Time}"
if test "${Time}" != ""; then
if [ "${Time}" -ge "${sec}" ]; then #大于等于5秒的sql
cat 3.txt >> sql5.log #追加到5秒集合中
fi
fi
done
#删除不需要的文件
rm ${SHELL_FOLDER}/temp.txt
rm ${SHELL_FOLDER}/newSlow.txt
}
send_mail()
{
if test "$IS_alert" = "1"; then #是否告警
back_size5=$(stat -c "%s" $SHELL_FOLDER/sql5.log)
if [[ $back_size5 > 1 ]];then
echo "出现慢sql(超过${sec}s),附件为sql语句。服务器IP:${Ip_Addr}" | \
mail -s "慢sql语句(超过${sec}s),服务器IP:${Ip_Addr}" -a ${SHELL_FOLDER}/sql5.log ${Mail}
echo "" > ${SHELL_FOLDER}/sql5.log #发送完邮件后清空,等下次运行追加
fi
fi
}
help_()
{
cat <<EOF
Mysql slow 分析脚本 Version: ${Version}
Usage:
${0} [-xfmsah]
Options:
-x : Print Debug .
-f : MySQL slow SQL file .
-m : Mailing List .
-s : Slow SQL seconds .
-a : Alarm or not .
-h : Print Help .
EOF
exit 0
}
init
while getopts :xf:m:s:a:h? arg; do
case ${arg} in
x)
debug=x;
;;
f)
slowLogFile="$OPTARG";
;;
m)
Mail="$OPTARG";
;;
s)
sec="$OPTARG";
;;
a)
IS_alert="$OPTARG";
;;
h|?)
help_
;;
esac
done
shift $((OPTIND-1)); #参数移位
test "${debug}" = "x" && set -x;
main
Split_text
send_mail