奇怪的ZBX_NOTSUPPORTED问题一则

在监控linux硬件信息的时候,通过system.hw.chassis[serial]监控项来获取设备序列号。本机通过zabbix_agentd命令测试正常

1
2
3
4
[root@localhost ~]# zabbix_agentd -t system.sw.os[name]
system.sw.os[name] [s|Oracle Linux Server 7.8]
[root@localhost ~]# zabbix_agentd -t system.hw.chassis[model]
system.hw.chassis[model] [s|ProLiant DL360 Gen10]

但是在proxy服务器上通过zabbix_get命令获取数据时却发现监控项不支持

1
2
3
4
[root@zabbix-proxy ~]# zabbix_get -s 192.168.2.11 -k system.sw.os[name]
Oracle Linux Server 7.8
[root@zabbix-proxy ~]# zabbix_get -s 192.168.2.11 -k system.hw.chassis[model]
ZBX_NOTSUPPORTED: Cannot obtain hardware information.
阅读更多

Zabbix监控GBK字符集的oracle

监控oracle有很多方式,目前主要使用的是通过第三方软件orabbix,它是通过jdbc连到各个oracle数据库上去执行sql,效率还可以,只是目前有个新需求,有个业务监控返回结果必须含有中文,而orabbix中无法配置字符集 ,导致存放到zabbix中时就会乱码,所以只能换一种方式,采用自带的database monitor来监控。整个配置过程很简单,主要是记录下字符集的转换配置。

Linux安装oracle客户端

下载linux客户端rpm包

1
2
3
4
5
6
[root@localhost oracle linux client]# ll
total 54436
-rw-r--r-- 1 root root 54172532 Jul 23 16:30 oracle-instantclient19.8-basic-19.8.0.0.0-1.x86_64.rpm
-rw-r--r-- 1 root root 612416 Jul 23 16:29 oracle-instantclient19.8-devel-19.8.0.0.0-1.x86_64.rpm
-rw-r--r-- 1 root root 246760 Jul 23 16:29 oracle-instantclient19.8-odbc-19.8.0.0.0-1.x86_64.rpm
-rw-r--r-- 1 root root 702872 Jul 23 16:29 oracle-instantclient19.8-sqlplus-19.8.0.0.0-1.x86_64.rpm

安装rpm包

1
rpm -ivh oracle-instantclient19.8-*.rpm

安装完以后会生成对应的oracle目录/usr/lib/oracle/19.8/client64

新建tns目录

1
2
3
[root@zabbix-wh-proxy client64]# mkdir -p network/admin

touch tnsnames.ora

设置环境变量

1
2
3
4
export ORACLE_HOME=/usr/lib/oracle/19.8/client64
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib64:$LD_LIBRARY_PATH
export TNS_ADMIN=$ORACLE_HOME/network/admin
export PATH=$PATH:$ORACLE_HOME/bin:$HOME/bin

Linux安装odbc

1
yum -y install unixODBC unixODBC-devel

配置文件主要为两个,/etc/odbc.ini/etc/odbcinst.ini,后者配置驱动,前者配置数据库参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
cat /etc/odbcinst.ini

[PostgreSQL]
Description=ODBC for PostgreSQL
Driver=/usr/lib/psqlodbcw.so
Setup=/usr/lib/libodbcpsqlS.so
Driver64=/usr/lib64/psqlodbcw.so
Setup64=/usr/lib64/libodbcpsqlS.so
FileUsage=1

[MySQL]
Description=ODBC for MySQL
Driver=/usr/lib/libmyodbc5.so
Setup=/usr/lib/libodbcmyS.so
Driver64=/usr/lib64/libmyodbc5.so
Setup64=/usr/lib64/libodbcmyS.so
FileUsage=1

[MySQL ODBC 8.0 Unicode Driver]
Driver=/usr/lib64/libmyodbc8w.so
UsageCount=1

[MySQL ODBC 8.0 ANSI Driver]
Driver=/usr/lib64/libmyodbc8a.so
UsageCount=1


[FreeTDS]
Driver = /usr/lib64/libtdsodbc.so.0

[OracleDriver]
Description= ODBC for Oracle
Driver= /usr/lib/oracle/19.8/client64/lib/libsqora.so.19.1

添加oracle的驱动到末尾,driver指向lib路径

1
2
3
4
5
6
7
cat /etc/odbc.ini

[test]
Driver = OracleDriver
ServerName = 192.168.2.112:1521/pdb12c
UserID = zabbix
Password = zabbix

测试配置

1
2
3
4
5
6
7
8
9
10
isql test

+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+

这里很简单就配置完了,只需要在web端添加database monitor就可以了,odbc.ini里设置的test就是唯一DSN

字符集问题

zabbix后台存放数据的库是mysql,是utf8字符集,在监控字符集为gbk的oracle时,会碰到一个问题,就是当sql返回结果含有中文时就会乱码,由于我之前所有的oracle监控都是通过orabbix来完成,对于这个问题始终无法解决。而通过odbc监控时,则可以通过修改odbc的配置来实现字符集的转换。

在odbc.ini里添加环境变量参数

1
DMEnvAttr = SQL_ATTR_UNIXODBC_ENVATTR={NLS_LANG=SIMPLIFIED CHINESE.AL32UTF8}

然后重新执行sql,就可以得到正确的中文返回结果。

Zabbix监控ogg延迟情况

最近ogg出现了一点问题,没有及时发现,于是考虑将ogg的监控也纳入zabbix当中来。对于这一类监控,考虑的地方不单单在于如何监控,而是善用zabbix的模板、自动发现等功能来实现,这样会方便配置以及后期的可扩展性。

首先对ogg的运行情况查看通常是通过info all命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MANAGER     RUNNING                                           
EXTRACT RUNNING EPRISK 00:00:03 00:00:08
EXTRACT RUNNING ERDMEDW 00:00:04 00:00:06
EXTRACT RUNNING ESHDW 00:00:00 00:00:01
EXTRACT RUNNING PCIF 00:00:00 00:00:08
EXTRACT RUNNING PEIF 00:00:00 00:00:08
EXTRACT RUNNING PHG 00:00:00 00:00:08
EXTRACT RUNNING PQH 00:00:00 00:00:06
EXTRACT RUNNING PRISKMGR 00:00:00 00:00:08
EXTRACT RUNNING PSHDW 00:00:00 00:00:06
REPLICAT RUNNING RCIF 00:00:10 00:00:06
REPLICAT RUNNING REDMDB1 00:00:00 00:00:01
REPLICAT RUNNING REDQDB1 00:00:00 00:00:07
REPLICAT RUNNING REIF 00:00:00 00:00:00
REPLICAT RUNNING REPWIND 00:00:00 00:00:06
REPLICAT RUNNING REPWIND2 00:00:00 00:00:00
REPLICAT RUNNING REPWIND3 00:00:00 00:00:05
REPLICAT RUNNING REPWIND4 00:00:00 00:00:04
REPLICAT RUNNING RZNMGR 00:00:00 00:00:00
REPLICAT RUNNING RZNMGRC 00:00:00 00:00:01

这里总共有19个抽取、传输进程,根据实际需求只需要做到分钟级别监控即可,所以筛选出4列,分别为运行状态、进程名、lag时间、time列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
echo "info all"|ggsci|egrep 'EXTRACT|REPLICAT'|awk -F"[ ]+|:" '{print $2,$3,$4*60+$5,$7*60+$8}'

RUNNING EPRISK 0 0
RUNNING ERDMEDW 0 0
RUNNING ESHDW 0 0
RUNNING PCIF 0 0
RUNNING PEIF 0 0
RUNNING PHG 0 0
RUNNING PQH 0 0
RUNNING PRISKMGR 0 0
RUNNING PSHDW 0 0
RUNNING RCIF 0 0
RUNNING REDMDB1 0 0
RUNNING REDQDB1 0 0
RUNNING REIF 0 0
RUNNING REPWIND 0 0
RUNNING REPWIND2 0 0
RUNNING REPWIND3 0 0
RUNNING REPWIND4 0 0
RUNNING RZNMGR 0 0
RUNNING RZNMGRC 0 0

通过shell将获取到的数据写入中间文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
all()
{
source /home/oracle/.bash_profile;echo "info all"|ggsci|egrep 'EXTRACT|REPLICAT'|awk -F"[ ]+|:" '{print $2,$3,$4*60+$5,$7*60+$8}'
}

name()
{
source /home/oracle/.bash_profile;echo "info all"|ggsci|egrep 'EXTRACT|REPLICAT'|awk '{print $3}'
}

a=$1
case "$a" in
all)
all
;;
name)
name
;;
*)
echo -e "Usage: ./`basename $0` [all|name]"
esac

为了满足zabbix自动发现的要求,返回值必须要是json格式,所以可以对上面的数据进行格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/usr/bin/env python  
#coding:utf-8
import os, json, sys
f = open("/etc/zabbix/scripts/ogg.cfg","r")
lines = f.readlines()
ogg_list=[]
ogg_dict={"data":None}
for line in lines:
if line.startswith('#')or not line.split():
continue
line=line.strip('\n')
status=line.split()[0]
name=line.split()[1]
lag=line.split()[2]
time=line.split()[3]
pdict={}
pdict["{#NAME}"]=name
pdict["{#STATUS}"]=status
pdict["{#LAG}"]=lag
pdict["{#TIME}"]=time
ogg_list.append(pdict)
f.close()
ogg_dict["data"]=ogg_list
var = sys.argv[1]
var2 = sys.argv[2]
jsonStr = json.dumps(ogg_dict, sort_keys=True, indent=4)
#print jsonStr

def get_lag(name):
l = [x.get("{#LAG}") for t, x in enumerate(ogg_list) if x.get("{#NAME}") == name]
print l[0]

def get_time(name):
l = [x.get("{#TIME}") for t, x in enumerate(ogg_list) if x.get("{#NAME}") == name]
print l[0]

def get_status(name):
l = [x.get("{#STATUS}") for t, x in enumerate(ogg_list) if x.get("{#NAME}") == name]
print l[0]

def get_json():
jsonStr = json.dumps(ogg_dict, sort_keys=True, indent=4)
print jsonStr

def ogg(var, var2):
if var == 'json':
get_json()
else:
if var2 == 'lag':
get_lag(var)
elif var2 == 'status':
get_status(var)
else:
get_time(var)
ogg(var, var2)

最后得到的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
{
"data": [
{
"{#LAG}": "0",
"{#NAME}": "EPRISK",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "ERDMEDW",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "ESHDW",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "PCIF",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "PEIF",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "PHG",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "PQH",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "PRISKMGR",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "PSHDW",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "RCIF",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "REDMDB1",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "REDQDB1",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "REIF",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "REPWIND",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "REPWIND2",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "REPWIND3",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "REPWIND4",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "RZNMGR",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
},
{
"{#LAG}": "0",
"{#NAME}": "RZNMGRC",
"{#STATUS}": "RUNNING",
"{#TIME}": "0"
}
]
}

数据都已经获取到,到这里脚本就准备完毕,需要添加两个自定义key

1
2
UserParameter=ogg.discovery,/etc/zabbix/scripts/ogg_delay.py json test
UserParameter=ogg_delay[*],/etc/zabbix/scripts/ogg_delay.py $1 $2

在zabbix上新建模板,配置宏参数以及新增监控项和触发器等,最后只需要将模板添加到对应监控的主机即可