2019.6.5 更新:
前端无任何变化但是显示需求变了。
改变入下:
1.监控项不再显示 xxx on 3306(主机宏的端口)
而显示为 xxx on mysqlshili (端口处理为实例名)
discovery_mysql.sh 变化为:
res=`for PORT_NUMBER in \`echo $1 | sed "s/_/\n/g"\` ;do ps -o ruser=userl-orLongName -e -o pid,ppid,c,stime,tty,time,cmd |grep '/mysql/app/bin/mysqld'| grep "$PORT_NUMBER" |grep -v grep | awk -F" " '{print $1}' ; done`;
port=($res)
printf '{\n'
printf '\t"data":[\n'
for key in ${!port[@]}
do
if [[ "${#port[@]}" -gt 1 && "${key}" -ne "$((${#port[@]}-1))" ]];
then
printf '\t {\n'
printf "\t\t\t\"{#MYSQLPORT}\":\"${port[${key}]}\"},\n"
else [[ "${key}" -eq "((${#port[@]}-1))" ]]
printf '\t {\n'
printf "\t\t\t\"{#MYSQLPORT}\":\"${port[${key}]}\"}\n"
fi
done
printf '\t ]\n'
printf '}\n'
截取方式: grep端口号相应的进程 然后取出该进程的 用户名。
对应 的 所有脚本 都会变化的,截取方式有变化(根据需求来)
主从监控:
主从状态: semi_master_status
semi_slave_status
slave_IO_running
slave_SQL_running
second_behind_master
上面四个key做优化,不管 他们的输出是 yes no on off,写成判定条件
只要他们是正常的,就显示1, 错误的就显示0.
mysql_repl.sh
var=$1
MYSQL_shili=$2
MYSQL_SOCk_DIR="--socket=/$MYSQL_shili/log/mysql.sock" ;
mysql=/mysql/app/bin/mysql
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxx
STATUS_REPL=`${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show global variables like 'read_only';" 2> /dev/null|grep -i read_only |awk -F" " '{print $2}' `;
VALUE=`${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show slave status\G;" 2> /dev/null |grep "\b${var}\b"|awk -F" " '{print $2}' ` ;
#echo $VALUE;
if [[ $STATUS_REPL == OFF ]] # master
then
echo 1; # value of Slave_IO_Running\Slave_SQL_Running is null
elif [[ $STATUS_REPL == ON ]] #slave
then
if [[ $1 == Seconds_Behind_Master ]]
then echo $VALUE;
elif [[ $VALUE == Yes ]] # value of Slave_IO_Running\Slave_SQL_Running is Yes
then echo 1;
else
echo 0;
fi
else
echo 2; # value of readonly has problem
fi
mysql_repl_semi_sync.sh
mysql=/mysql/app/bin/mysql
var=$1
MYSQL_shili=$2
MYSQL_SOCk_DIR="--socket=/$MYSQL_shili/log/mysql.sock" ;
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxx
STATUS_REPL=`${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show global variables like 'read_only';" 2> /dev/null|grep -i read_only |awk -F" " '{print $2}' `;
VALUE_master=`${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show global variables like 'rpl_semi_sync_master_enabled' ;" 2> /dev/null |grep -v Variable_name | awk '{print $2}'` ;
VALUE_slave=`${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show global variables like 'rpl_semi_sync_slave_enabled' ;" 2> /dev/null |grep -v Variable_name | awk '{print $2}'` ;
#$mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -S$MYSQL_SOCk_DIR -e "show global status;" |grep -v Variable_name|grep "\b$var\b"|awk '{print $2}' ;
if [[ $STATUS_REPL == OFF ]] #master
then
if [[ $1 == Rpl_semi_sync_master_status ]] # key = master_status
then
if [[ $VALUE_master == ON ]] # master_enabled = on
then
echo 1;
elif [[ $VALUE_master == OFF ]] # master_enabled = off
then
echo 0;
else
echo 2; # value of master_enabled has problem
fi
elif [[ $1 == Rpl_semi_sync_slave_status ]] # key = slave_status
then
if [[ $VALUE_slave == ON ]] # slave_enabled = on
then
echo 1;
elif [[ $VALUE_slave == OFF ]] # slave_enabled = off
then
echo 0;
else
echo 2; # value of slave_enabled has problem
fi
else
echo 3; #value of $1 has problem
fi
elif [[ $STATUS_REPL == ON ]] # slave
then
if [[ $1 == Rpl_semi_sync_master_status ]] # key = master_status
then
if [[ $VALUE_master == ON ]] # master_enabled = on
then
echo 0;
elif [[ $VALUE_master == OFF ]] # master_enabled = off
then
echo 1;
else
echo 2;
fi
elif [[ $1 == Rpl_semi_sync_slave_status ]] # key = slave_status
then
if [[ $VALUE_slave == ON ]]
then
echo 1;
elif [[ $VALUE_slave == OFF ]]
then
echo 0;
else
echo 2;
fi
else
echo 3;
fi
else
echo 4; #$STATUS_REPL value of readonly has problem
fi
下面依次是其他脚本做的修改:
mysql_filestype.sh
var=$1
MYSQL_shili=$2
MYSQL_DIR="/$MYSQL_shili/" ;
df -h "${MYSQL_DIR}${var}" |grep -v Filesystem |awk -F" " '{print $5}' | awk -F"%" '{print $1}' ;
mysql_ping.sh
MYSQL_shili=$1;
#MYSQL_PORT=`ps -ef | grep /mysql/app/bin/mysqld | grep port |grep $1 | grep -v grep | awk -F"=" '{print $10}'` ;
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xxx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxx
mysqladmin=/mysql/app/bin/mysqladmin ;
MYSQL_SOCk_DIR="--socket=/$MYSQL_shili/log/mysql.sock" ;
${mysqladmin} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} ping 2> /dev/null |grep 'alive'|wc -l ;
mysql_status2
mysql=/mysql/app/bin/mysql
var=$1
MYSQL_shili=$2
#MYSQL_PORT=`ps -ef | grep /mysql/app/bin/mysqld | grep port |grep $2 | grep -v grep | awk -F"=" '{print $10}'` ;
MYSQL_SOCk_DIR="--socket=/$MYSQL_shili/log/mysql.sock" ;
#MYSQL_USER=$2
#MYSQL_PASSWORD=$3
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xxx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxx
MYSQL_SOCk_DIR=`ps -ef |grep '/mysql/app/bin/mysqld'| grep "${MYSQL_PORT}" |grep -v 'grep' | awk -F" " '{print $16}'` ;
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show global status;" 2> /dev/null |grep -v Variable_name|grep "\b${var}\b"|awk '{print $2}' ;
mysql_version.sh
MYSQL_shili=$1;
MYSQL_SOCk_DIR="--socket=/$MYSQL_shili/log/mysql.sock" ;
mysql=/mysql/app/bin/mysql ;
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xxx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxxx
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "select version();" 2> /dev/null |awk 'END {print}'
最后是 这些脚本的生效文件:
mysql_status_many.conf
UserParameter=mysql.discovery[*],/patrol/zabbix/bin/duoshili_discovery/discovery_mysql.sh $1
UserParameter=mysql.status_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_status2 $1 $2
UserParameter=mysql.ping_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_ping.sh $1
UserParameter=mysql.version_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_version.sh $1
UserParameter=mysqlcheck_repl[*],/patrol/zabbix/bin/duoshili_discovery/mysql_repl.sh $1 $2
UserParameter=mysql.filestyle_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_filestype.sh $1 $2
UserParameter=mysqlcheck_repl_sync[*],/patrol/zabbix/bin/duoshili_discovery/mysql_repl_semi_sync.sh $1 $2
———————————————————————————————————————————————
##########################################################
######################################################
zabbix监控mysql多实例
需求: agent上起了多了 mysql实例,占用不同的端口
agent 仅在初始状况下,塞入脚本和 键配置,然后重启。 以后维护的时候(mysql端口变动),要做到 不能 动agent,力争 只在 web端 或者server端做修改 就能自动监控到对应端口。
用到的主要工具: 宏(分为模板宏,主机宏,自动发现宏)
主机宏格式: {$MACRO} (直接就可以 填 值)
自动发现宏:{#MACRO} (需要配合 创建的 key 取值)
大体架构:
1.agent主机 -- agent 主机创建 宏变量 $MYSQLPORT ,宏变量的值为 Discovery rules的 自动发现脚本参数
2.模板 -- 模板里创建自动发现规则,靠的是自动发现脚本,得到自动发现宏变量。
3.监控项-- 在Discovery rules 里创建监控项,监控项名称和key值里都有自动发现宏变量,会自动生成相关端口的监控项
4.客户端 脚本和键创建,来支持整个架构运行
搭建步骤
1.创建模板
多实例模板.PNG
因为这个模板是 克隆 的默认 mysql监控模板,可以忽略 items,triggers。 监控项都在 Discovery rules 里。
2.为模板添加 自动发现宏(自动发现宏声明的途径就是下图的脚本,脚本里只有生成固定的格式,zabbix就会认定他是 自动发现宏)
自动发现规则.PNG
上图 里的 mysql.discovery 就是获取 自动发现宏的 脚本,脚本是放在 agent端。
后面的 $MYSQLPORT 为此脚本执行时带的参数,$MYSQLPORT 是主机宏。
discovery rule 右边的 filters 是过滤规则的意思,比方你 只想取脚本里的 某某 自动发现宏,就可以在里面设置。 这里就只有一个自动发现宏,所有不做 配置。
3.创建监控项(监控项和监控的脚本都是要改的,因为自动发现功能,至少脚本会多了一个参数)
图片.png
4.创建 主机宏
主机宏.PNG
点开主机,添加主机宏,宏名称是 自动发现脚本里的 参数, 宏的值就是 此 主机上需要监控的端口。
这样就实现了 只要改动主机宏的 值,就可以改变主机宏的监控项。
脚本展示:
1.discovery_mysql.sh 自动发现端口脚本 (网上抄的脚本做了修改)
res=`echo $1| sed "s/_/\n/g"`;
port=($res)
printf '{\n'
printf '\t"data":[\n'
for key in ${!port[@]}
do
if [[ "${#port[@]}" -gt 1 && "${key}" -ne "$((${#port[@]}-1))" ]];
then
printf '\t {\n'
printf "\t\t\t\"{#MYSQLPORT}\":\"${port[${key}]}\"},\n"
else [[ "${key}" -eq "((${#port[@]}-1))" ]]
printf '\t {\n'
printf "\t\t\t\"{#MYSQLPORT}\":\"${port[${key}]}\"}\n"
fi
done
printf '\t ]\n'
printf '}\n'
执行实例: 以_ 为分隔符,格式化输出 自动发现宏
./discovery_mysql.sh 3306_3307_3308
{
"data":[
{
"{#MYSQLPORT}":"3306"},
{
"{#MYSQLPORT}":"3307"},
{
"{#MYSQLPORT}":"3308"}
]
}
2.mysql_filestype.sh 监控mysql的一些挂载盘
var=$1
MYSQL_PORT=$2
MYSQL_NAME=`ps -ef |grep '/mysql/app/bin/mysqld'| grep "$MYSQL_PORT" |grep -v grep | awk -F" " '{print $11}' |awk -F"/" '{print $2}'` ;
MYSQL_SOCk_DIR="/$MYSQL_NAME/" ;
df -h "${MYSQL_SOCk_DIR}${var}" |grep -v Filesystem |awk -F" " '{print $5}' | awk -F"%" '{print $1}' ;
3.mysql_ping.sh 监控mysql状态
MYSQL_PORT=$1;
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xxx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxxxx
mysqladmin=/mysql/app/bin/mysqladmin ;
MYSQL_SOCk_DIR=`ps -ef |grep 'mysql'| grep "${MYSQL_PORT}" |grep -v 'grep' | awk -F" " '{print $16}'` ;
${mysqladmin} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} ping 2> /dev/null |grep 'alive'|wc -l ;
注意: 这边连接实例 都是 mysql -u -p -S /xxx/mysql.sock
但是后来发现部分客户端总是无法正确显示值,而且就是这条 语句报错, 感觉是环境变量的问题
所以拿 --socket=/xxx/mysql.sock 来代替 -S/xxx/mysql.sock 。 这里的变量${MYSQL_SOCk_DIR} 就是--socket=/xxx/mysql.sock 。
4.mysql_repl.sh mysql主从状态监控
var=$1
MYSQL_PORT=$2
MYSQL_SOCk_DIR=`ps -ef |grep 'mysql'| grep "${MYSQL_PORT}" |grep -v 'grep' | awk -F" " '{print $16}'` ;
mysql=/mysql/app/bin/mysql
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xxx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxxx
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show slave status\G;" 2> /dev/null |grep "\b${var}\b"|awk -F" " '{print $2}' ;
主从状态 有几个端口的值是 空的, 这个得 具体问题具体设置
5.mysql_status2 mysql性能之类的监控
mysql=/mysql/app/bin/mysql
var=$1
MYSQL_PORT=$2
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xxx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxxxx
MYSQL_SOCk_DIR=`ps -ef |grep 'mysql'| grep "${MYSQL_PORT}" |grep -v 'grep' | awk -F" " '{print $16}'` ;
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "show global status;" 2> /dev/null |grep -v Variable_name|grep "\b${var}\b"|awk '{print $2}' ;
发现有些监控项 或因为数字过长而无法显示,待解决
6.mysql_version.sh mysql版本监控
MYSQL_PORT=$1;
MYSQL_SOCk_DIR=`ps -ef |grep 'mysql'| grep "${MYSQL_PORT}" |grep -v 'grep' | awk -F" " '{print $16}'` ;
mysql=/mysql/app/bin/mysql ;
[ "${MYSQL_USER}" = '' ] && MYSQL_USER=xxx
[ "${MYSQL_PASSWORD}" = '' ] && MYSQL_PASSWORD=xxxx
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_SOCk_DIR} -e "select version();" 2> /dev/null |awk 'END {print}'
7.mysql_status_many.conf 生成可用键 配置文件
UserParameter=mysql.discovery[*],/patrol/zabbix/bin/duoshili_discovery/discovery_mysql.sh $1
UserParameter=mysql.status_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_status2 $1 $2
UserParameter=mysql.ping_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_ping.sh $1
UserParameter=mysql.version_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_version.sh $1
UserParameter=mysqlcheck_repl[*],/patrol/zabbix/bin/duoshili_discovery/mysql_repl.sh $1 $2
UserParameter=mysql.filestyle_many[*],/patrol/zabbix/bin/duoshili_discovery/mysql_filestype.sh $1 $2