安装pnp4nagios后,我写了一个数据转换脚本,把我的数据按「pnp4nagios的数据格式」输出到spool目录,在「pnp4nagios的安装」中我启动了npcd进程,并且配置spool目录为/diska/pnp4nagios/spool
,因此流程为:
- 启动npcd进程
/etc/init.d/npcd start
- 我的数据转换脚本以
perfdata_
开头生成文件,输出到/diska/pnp4nagios/spool
- npcd扫描到文件,调用脚本
/home/pnp4nagios/libexec/process_perfdata.pl
处理数据,写rrd文件 - 在日志目录
/diska/pnp4nagios/perf_logs
查看npcd.log
和perfdata.log
对于样例数据:
- DATATYPE::SERVICEPERFDATA TIMET::1378779841 HOSTNAME::zh_v542 SERVICEDESC::PING SERVICECHECKCOMMAND::check_icmp SERVICEPERFDATA::rta=92.412ms;200.000;500.000;0; pl=0%;40;80;; rtmax=97.281ms;;;; rtmin=86.727ms;;;;
经处理后,在rrd目录/diska/pnp4nagios/perfdata
会生成一个zh_v542
子目录,目录下有ping.xml
和ping.rrd
两个文件。当我们访问http://localhost/pnp4nagios/index.php/graph?host=zh_v542&srv=check_icmp
时,pnp4nagios的处理大概为:
- 扫描参数
host
下的所有xml文件,读取到/diska/pnp4nagios/perfdata/zh_v542/ping.xml
,显示目前有一个ping的服务 - 扫描参数
srv
指定的模板,扫描/home/pnp4nagios/share/templates
和/home/pnp4nagios/share/templates.dist
,按文件名匹配一个check_icmp.php
的模板文件 - 找到
/home/pnp4nagios/share/templates.dist/check_icmp.php
,模板文件里配置了2个信息:RRD文件的路径、如何画rrd图。 - 如果找不到匹配的模板,则使用默认模板
default.php
- 从
/diska/pnp4nagios/perfdata/zh_v542/ping.rrd
中读取数据,根据模板的rrd函数,画出rrd图。这需要对rrd的一些画图方式有一定的了解。
一个check_icmp.php的模板内容大概为:
<?php
#
# Copyright (c) 2006-2010 Joerg Linge (http://www.pnp4nagios.org)
# Plugin: check_icmp [Multigraph]
#
# RTA
#
$ds_name[1] = "Round Trip Times";
$opt[1] = "--vertical-label \"RTA\" --title \"Ping times\" ";
$def[1] = rrd::def("var1", $RRDFILE[1], $DS[1], "AVERAGE") ;
$def[1] .= rrd::gradient("var1", "ff5c00", "ffdc00", "Round Trip Times", 20) ;
$def[1] .= rrd::gprint("var1", array("LAST", "MAX", "AVERAGE"), "%6.2lf $UNIT[1]") ;
$def[1] .= rrd::line1("var1", "#000000") ;
if($WARN[1] != ""){
if($UNIT[1] == "%%"){ $UNIT[1] = "%"; };
$def[1] .= rrd::hrule($WARN[1], "#FFFF00", "Warning ".$WARN[1].$UNIT[1]."\\n");
}
if($CRIT[1] != ""){
if($UNIT[1] == "%%"){ $UNIT[1] = "%"; };
$def[1] .= rrd::hrule($CRIT[1], "#FF0000", "Critical ".$CRIT[1].$UNIT[1]."\\n");
}
#
# Packets Lost
$ds_name[2] = "Packets Lost";
$opt[2] = "--vertical-label \"Packets lost\" -l0 -u105 --title \"Packets lost\" ";
$def[2] = rrd::def("var1", $RRDFILE[2], $DS[2], "AVERAGE");
$def[2] .= rrd::gradient("var1", "ff5c00", "ffdc00", "Packets Lost", 20) ;
$def[2] .= rrd::gprint("var1", array("LAST", "MAX", "AVERAGE"), "%3.0lf $UNIT[2]") ;
$def[2] .= rrd::line1("var1", "#000000") ;
$def[2] .= rrd::hrule("100", "#000000") ;
if($WARN[2] != ""){
if($UNIT[2] == "%%"){ $UNIT[2] = "%"; };
$def[2] .= rrd::hrule($WARN[2], "#FFFF00", "Warning ".$WARN[2].$UNIT[2]."\\n");
}
if($CRIT[2] != ""){
if($UNIT[2] == "%%"){ $UNIT[2] = "%"; };
$def[2] .= rrd::hrule($CRIT[2], "#FF0000", "Critical ".$CRIT[2].$UNIT[2]."\\n");
}
模板主要是2个数组$opt
和$def
, 可以使用xml文件里的字段,比如DS, NAME, RRDFILE
等,具体的见pnp4nagios关于模板的介绍吧。对于字段不确定的模板,可以这样写
<?php
foreach ($this->DS as $KEY=>$VAL) {
#$DATA[$VAL["NAME"]] = $VAL;
$DATA[$VAL["LABEL"]] = $VAL;
}
ksort($DATA);
# print $DATA to browser
#throw new Kohana_exception(print_r($DATA,TRUE));
$i = 0;
foreach ($DATA as $key => $val){
$title = "$key";
$ds_name[$i] = "$key";
$opt[$i] = "-b 1000 --vertical-label \"%\" -l0 --title \"$hostname $title\" ";
$key = $val["NAME"];
$def[$i] = rrd::def("$key", $val["RRDFILE"], 1, "AVERAGE");
$def[$i] .= rrd::line1("$key", "#007500", "$title");
$def[$i] .= rrd::gprint("$key", array("LAST", "AVERAGE", "MAX"), "%10.2lf%s");
$i ++;
}
#throw new Kohana_exception(print_r($def,TRUE));
?>
对于模板,我想说的一个tip,可以通过throw new Kohana_exception(print_r($def,TRUE));
,抛出一个异常信息到浏览器中,查看数据内容,这对于我刚接触模板的人来说,提供了很大的帮助。
到此还以为可以完成工作,没想到npcd调用process_perfdata.pl的单进程处理速度并不理想,3.5w条的数据写入RRD文件,处理了将近30分钟,磁盘IO也很高,而实际上这需要在1分钟内处理完成的。
还要换个方式,后续再记。
– EOF –