秦悦明的运维笔记

zabbix模块编程

1.module简介

其实就是一个动态扩展库,可以动态的被agent加载,用来扩展agent本身没有的功能,你可以把一些item写进去,用c语言来高效实现。
源码自带了一个dummy模块,很好的一个例子,代码注释非常明确。

2.module用法

在config文件里面写入

1
LoadModule=xx.so

重启agent即可加载,一般是有如下日志:

1
2
16784:20170603:142839.965 using configuration file: /etc/zabbix/zabbix_agentd.conf
16784:20170603:142839.965 loaded modules: tcpcount.so

说明已经加载完成。以自带的dummy为例,我们先是在dummy目录下make,

1
2
3
4
#make
gcc -fPIC -shared -o dummy.so dummy.c -I../../../include
#ls
dummy.c dummy.so Makefile README

然后是加载模块,默认要放到/usr/lib64/zabbix/modules/下面:

1
LoadModule=dummy.so

进行测试:

1
2
# zabbix_get -s 127.0.0.1 -k dummy.ping
1
1
2
#zabbix_get -s 127.0.0.1 -k dummy.echo[qym]
qym
1
2
# zabbix_get -s 127.0.0.1 -k dummy.random[1,1000]
486

3. 编码

其实上面三个例子已经给了很好的诠释,首先是定义函数

1
int zbx_module_dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result)

函数返回SYSINFO_RET_OK或者SYSINFO_RET_FAIL. result用SET_XXX_RESULT来设置,比如ping返回1

1
SET_UI64_RESULT(result, 1);

echo返回字符串:

1
SET_STR_RESULT(result, strdup(param));

参数怎么获取呢,很简单有个get_rparam宏:

1
2
3
param1 = get_rparam(request, 0);
param2 = get_rparam(request, 1);

基本的骨架都有了,照着改改就行了。我写了个tcp count的模块,跟netstat的实现原理差不多,就是解析/proc/net/tcp下面的信息,
主要用的是sscanf这个函数,每行解析就可以了,实现上面跟https://github.com/mutz0623/zabbix_TCP-state-count-module类似,但是我只统计服务器端指定port的连接数,而且他的sscanf实现略有些笨拙,可以简化。
核心代码如下:

1
2
3
4
5
6
7
while ((read = getline(&line, &len, fp)) != -1){
int st;
sscanf(line, "%*d: %*08x:%04x %*08x:%*04x %02x",&port,&st);
if(port == dport && st == dst)
c++;
}

可以根据st ,也就是tcp状态信息字段来count,st的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum {
TCP_ESTABLISHED = 1,
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING, /* Now a valid state */
TCP_MAX_STATES /* Leave at the end! */
};

一般主要是TCP_ESTABLISHED和TCP_TIME_WAIT比较常见,配合模板使用,效果杠杠的。