
#! /usr/bin/env bash
REDIS_CLI=redis-cli
SET_SLOW_LOG_MAX_LEN="CONFIG SET slowlog-max-len %s"
GET_SLOW_LOG_MAX_LEN="CONFIG GET slowlog-max-len"
SET_SLOW_LOG_TIME="CONFIG SET slowlog-log-slower-than %s"
PORT=
PASSWORD="?"
function monitor {
GET_SLOW_LOG="SLOWLOG GET $MAX_LENGTH"
LAST_ID_FILE="redis_slow_query_${PORT}.id"
printf "$SET_SLOW_LOG_MAX_LEN" $5 | $1${REDIS_CLI} -a $6 -h $2 -p $3> /dev/null
printf "$SET_SLOW_LOG_TIME" $4 | $1${REDIS_CLI} -a $6 -h $2 -p $3 > /dev/null
if [[ -f ./"$LAST_ID_FILE" ]] ; then
LAST_READ_ID=$(cat ./${LAST_ID_FILE}| tr -cd "[0-9]")
else
LAST_READ_ID=-1
fi
if [[ "$LAST_READ_ID" == "" ]];then
LAST_READ_ID=-1
fi
SLOW_LOG=$(echo ${GET_SLOW_LOG} | $1${REDIS_CLI} -a $6 -h $2 -p $3 -d "###")
CURRENT_ID=$(echo "SLOWLOG GET 1" | $1${REDIS_CLI} -a $6 -h $2 -p $3} | awk 'BEGIN{FS="\n"; RS=""} {print $1}')
LOG_LEN=$(echo "SLOWLOG LEN" | $1${REDIS_CLI} -a $6 -h $2 -p $3})
ix=1
while (( ix < LOG_LEN )) ; do
jx=$((CURRENT_ID - ix))
SLOW_LOG=$(echo -e "$SLOW_LOG" | sed "s/\(###${jx}###[[:digit:]]\{1,\}###[[:digit:]]\{1,\}###[[:alpha:]]\{1,\}\)/###\1/g")
ix=$((ix + 1))
done
OUTPUT=$(echo "$SLOW_LOG" | awk 'BEGIN{RS="######";FS="###";MAX_READ_ID=-1;}
function assemble_query(str) {
gsub(/\|/, "<<VERTICAL>>",str);
if(QUERY == "") {
QUERY = str;
} else {
QUERY = QUERY " " str;
}
}
{
ix = 1;
QUERY = "";
while(ix <= NF) {
gsub(/[[:blank:]]*/, "", $ix);
if(ix == 1) {
ID = $1;
if(ID <= '$LAST_READ_ID') {
break;
}
if(ID > 'MAX_READ_ID') {
MAX_READ_ID=ID;
printf "%s<<MAX_ID>>", MAX_READ_ID;
}
} else if(ix == 2) {
TIMESTAMP = $2;
} else if(ix == 3) {
CONSUMED_TIME = $3;
} else {
assemble_query($ix);
}
++ix;
}
if(ix >= NF) {
printf "%s<<:>>%s<<:>>%s<<###>>", TIMESTAMP, CONSUMED_TIME, QUERY;
}
}')
echo $OUTPUT
if [[ "<<:>><<:>><<###>>" != "$OUTPUT" ]] ; then
MAX_READ_ID=$(echo ${OUTPUT} | awk 'BEGIN{FS="<<MAX_ID>>"} {print $1}' | tr -cd "[0-9]")
if [[ "" != "$MAX_READ_ID" ]] ; then
echo ${MAX_READ_ID} > ./${LAST_ID_FILE}
fi
export OUTPUT=$(echo ${OUTPUT} | awk 'BEGIN{FS="<<MAX_ID>>"} {print $2}')
else
OUTPUT=""
fi
}
function usage {
printf "\nUsage check_redis_slow_query:\n"
printf "\t<-f redis-cli可执行程序的路径>\n"
printf "\t[-H 设置Redis服务器的主机IP地址,默认为127.0.0.1]\n"
printf "\t[-p 设置连接Redis服务器的端口,默认为6379]\n"
printf "\t[-a 设置连接Redis服务器的密码,默认为空]\n"
printf "\t[-t 设置记录Redis慢查询语句的执行时间阈值,默认为10000微秒]\n"
printf "\t[-c 设置Redis记录慢查询语句的数目,超过此数值将删除最久的记录,默认为128]\n"
printf "\t-h 打印帮助信息\n"
}
while getopts :f:H:p:a:t:c:h arg ; do
case $arg in
f) BINFOLDER=$OPTARG;;
H) HOST=$OPTARG;;
p) PORT=$OPTARG;;
a) PASSWORD=$OPTARG;;
t) THRESHOLD=$OPTARG;;
c) MAX_LENGTH=$OPTARG;;
h) usage
exit 0;;
?) printf "无效的参数!\n"
usage
exit 3;;
esac
done
if [[ ${HOST} == "" ]] ; then
HOST=127.0.0.1
fi
if [[ ${PORT} == "" ]] ; then
PORT=6379
fi
if [[ ${PASSWORD} == "" ]] ; then
PASSWORD="?"
fi
if [[ ${THRESHOLD} == "" ]] ; then
THRESHOLD=10000
fi
if [[ ${MAX_LENGTH} == "" ]] ; then
MAX_LENGTH=128
fi
if [[ ${BINFOLDER} == "" ]] ; then
printf "${BINFOLDER}路径下不存在可执行的redis-cli程序.\n"
usage
exit 3
fi
monitor ${BINFOLDER} ${HOST} ${PORT} ${THRESHOLD} ${MAX_LENGTH} ${PASSWORD}
if [[ ! -z $OUTPUT ]] ; then
count=$(printf "%s" "$OUTPUT" | awk 'BEGIN{RS="<<###>>"} END{print NR}')
printf "${count}<<COUNT>>|Redis_Slow_Query<<###>>%s\n" "$OUTPUT"
exit 1
else
exit 0
fi