说明:
zabbix自带的默认模版里包括了很多监控项,有时候为了满足业务需求,需要根据自己的监控项目自定义监控项,这里介绍一种自定义监控项的方式。
背景:
postgresql有表的死亡元组一旦过高就会导致表膨胀影响使用,需要监控这值然后清理
1、首先编写自定义监控脚本
脚本名字:stations_hyz.sh
脚本目录(这个目录可以自定义):/etc/zabbix/zabbix_agentd.d/autovacuum_zabbix/
脚本内容:
cat stations_hyz.sh
#!/bin/bash
stations_hyz=`sudo -u postgres psql -U postgres -d hdsc_db -a -f /etc/zabbix/zabbix_agentd.d/autovacuum_zabbix/autovacuum.sql | grep stations_info_cache | awk -F '|' '{print $4}' | awk '{print $1}'`
if [ $stations_hyz -gt 100000 ];then ##将sql查询的值比对是否大于阈值10w
echo '1' ###也就是大于10w返回1给zabbix服务端告警
else ###正常返回0给zabbix服务端
echo '0'
fi
脚本说明:通过指定加载命令文件查询过滤筛选指定值并判断阈值,如果大于阈值则脚本反馈1,如果小于则返回0。你们有需要可以针对性修改获取的值,懂得原理即可。
下面这个是数据库查询死亡元组的命令,上面已经命名autovacuum.sql
[查询死亡元组参考链接]
cat autovacuum.sql
SELECT
c.relname 表名,
(current_setting('autovacuum_analyze_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_analyze_scale_factor')::NUMERIC(12,4))*reltuples AS 自动分析阈
值,
(current_setting('autovacuum_vacuum_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_vacuum_scale_factor')::NUMERIC(12,4))*reltuples AS 自动清理阈值
,
reltuples::DECIMAL(19,0) 活元组数,
n_dead_tup::DECIMAL(19,0) 死元组数
FROM
pg_class c
LEFT JOIN pg_stat_all_tables d
ON C.relname = d.relname
WHERE
reltuples > 0
AND n_dead_tup > (current_setting('autovacuum_analyze_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_analyze_scale_factor')::NUMERIC(12,4))*reltuples;
以下是使用Navicat Premium查询的截图
2、修改zabbix_agentd.conf配置文件
第一个:默认为0,此处我们将它改为1,改为1以后,表示用户自定义的脚本中可以包含特殊字符。
第二个:为我们自定义监控项,格式为:UserParameter=<键值>,<命令>。这里我们自定义键值为:=stations_hyz,要执行的命令为执行=stations_hyz.sh这个脚本。
说明:添加完成以后,重启zabbix_agentd才会生效。我这里添加了多个监控项,你们看需求添加。
3、zabbix服务端选择要增加监控项的主机
(1)创建模板以及应用集
(2)创建监控项
根据自定义键值填写监控项,自定义的键值只能手动输入,不能通过选择。
以下为具体的监控项配置内容:
(3) 创建触发器
以下是触发器具体内容:
在表达式里面选择监控项,并设置监控值为0还是1报警,
(4)添加成功后,在最新数据中查看是否获取到数据
正常获取
手机短信模拟测试截图:
至此,自定义监控项和自定义告警已添加完成,如果有其他监控需求,自己写监控脚本即可。
4、shell脚本小数计算,shell脚本统计执行时间
[小数计算参考链接]
[时间统计计算]
其中一个脚本是需要统计时间的,比如执行一个sql语句超过2s代表为异常,自定义的监控值啊不要杠。
间接的使用脚本执行启动和结束时间相减得出这个执行sql语句话费的时间。
因为需要经确到毫秒,所以需要比对大小,大于2秒返回值:
#!/bin/bash
startTime_s=`date +%S.%N | cut -b 1-5` ###sql语句查询启动时间,筛选小数点后两位
stations_info=`sudo -u postgres psql -U postgres -d hdsc_db -a -f /etc/zabbix/zabbix_agentd.d/autovacuum_zabbix/connector_time.sql | tail -3 | head -1 | awk '{print $1}'` ###调用sql语句查询命令
endTime_s=`date +%S.%N | cut -b 1-5` ###sql语句查询结束时间,筛选小数点后两位
sumTime=`awk 'BEGIN{print "'$endTime_s'" - "'$startTime_s'"}'`
####得出花费sql语句查耗时
expr $sumTime \> 2.00 ###sql语句查询耗时大于2.00s返回1,否则返回0
具体对应的zabbix和服务端配置都已经和上面类似一致,不再赘述,以及不详解zabbix对接短信配置。
5、查询sql语句超过指定时间告警
脚本原理看注释:
查询执行sql语句超过5分钟告警,
(是这里是过滤反选掉autovacuum语句执行,autovacuum语句是数据库用来定时死活元组的命令经常超过5分钟,不过滤掉他会一直告警频繁,并不需要监控autovacuum五分钟)
appdeploy@CDT-UAT-DB-02:/etc/zabbix/zabbix_agentd.d/autovacuum_zabbix$ cat select_time.sh
#!/bin/bash
##查询sql语句,反选autovacuum过滤前排第一个,因为执行时间过长得都有规律排在前面了。然后取分钟的2位数字来比较
select=`sudo -u postgres psql -U postgres -d hdsc_db -a -f /etc/zabbix/zabbix_agentd.d/autovacuum_zabbix/select_time.sql | head -11 | grep -v "autovacuum" | tail -1 | awk -F '|' '{print $4}' | awk -F ':' '{print $2}'`
##如果输出为空值,因为并不是每时每刻都有sql语句再执行,如果为空直接返回0值,zabbix采集到0是正常不触发告警,如果输出不为空直,那就是取值到分钟2位小数比如:06,然后取值分第二位
if [ -z "$select" ];then
echo '0'
exit
fi
select_time=`echo ${select:0-1}`
###如果取出的值分钟第二位大于4那就是执行超过五分钟了,输出为1,届时zabbix采集到1将告警
if [ $select_time -gt 4 ];then
echo '1'
else
echo '0'
fi
#
下面这个是select_time.sql
appdeploy@CDT-UAT-DB-02:/etc/zabbix/zabbix_agentd.d/autovacuum_zabbix$ cat select_time.sql
SELECT
pid,
datname AS db,
query_start AS start,
now() - query_start AS lap,
query
FROM pg_stat_activity
WHERE state <> 'idle' and query not like '%pg_stat_activity%' order by lap desc;
6、只过滤autovacuum
上面是反选过滤autovacuum语句得出其他所有语句超过5分钟告警,所以autovacuum这个语句也要监控,但是不是五分钟,设置50分钟告警即可。
appdeploy@CDT-UAT-DB-02:/etc/zabbix/zabbix_agentd.d/autovacuum_zabbix$ cat autovacuum_time.sh
##过滤出autovacuum语句大于1小时,这里取50分钟,大于5即可###
select=`sudo -u postgres psql -U postgres -d hdsc_db -a -f /etc/zabbix/zabbix_agentd.d/autovacuum_zabbix/select_time.sql | head -11 | grep autovacuum | tail -1| awk -F '|' '{print $4}' | awk -F ':' '{print $2}'`
if [ -z "$select" ];then
echo '0'
exit
fi
select_time=`echo ${select:0-0:1}`
#echo $select_time
#select_time=5
if [ $select_time -gt 4 ];then
echo '1'
else
echo '0'
fi
#
下面这个是select_time.sql
和5步骤的sql语句一样。不同的是筛选过滤那里。
专业从事搬砖多年,还是在继续搬砖中,厚积薄发~