2.2 插件
我们曾讨论过,Nagios是一个调度和通知框架,通过调用称为插件的小型监控程序工作。接下来,我们将了解这些插件究竟是什么,它们如何与Nagios交互以及如何实现一个全功能的监控系统。
2.2.1 退出代码
首先,各位读者要明白,无须从头编写自己的监控系统。Nagios插件项目 提供了用户贡献的一系列插件,这些插件能够提供用户渴望的任何监控系统的功能。项目中包含了运行在监控系统上的插件,比如端口扫描工具、ICMP和SNMP查询工具,也包括设计用于远程执行的工具,比如CPU和内存利用率的检测程序。除该项目之外,Nagios Exchange中还提供了上千个专用的插件,地址是www.nagiosexchange.com。
最终无论是亲自编写插件还是使用已有的脚本,作为Nagios的插件都相当容易。只要脚本或程序按照Nagios要求,提供规范的退出代码就可以作为Nagios的插件了,如表2-1所示。
表2-1 Nagios插件退出代码
字面上来说,程序作为插件唯一要遵守的原则就是提供退出代码。任何能够提供退出代码 的编程或脚本语言都可以用来编写Nagios插件。插件的具体工作步骤如下所述:
1.从目标主机上收集信息,比如当前负载或者它的首页文件index.html;
2.将收集的信息与期望状态或阈值进行比对;
3.根据比对结果,提供对应退出代码。
服务定义将指定使用的插件以及其他相关信息,比如服务名称、检测执行的频率等。Nagios负责调度并执行服务定义中指定的插件,并有选择地为插件提供阈值进行比较。当插件完成了它的“工作”后,会返回4个退出代码之一:0表示“正常”,1表示“警告”,2表示“严重”,3表示“未知”。Nagios解析插件的退出代码并据此做响应。当Nagios接收到有问题的代码时,它会更新服务状态并根据配置决定是否联系相关人员,具体内容稍后会讲解。
代码2-1展示的是“从头开始”使用Shell重写的Ping脚本,该脚本可以作为Nagios插件。
代码2-1 Ping插件
#!/bin/sh if ping -qc 5 server1 then exit 0 else exit 2 fi
代码2-1中的ping命令还是向服务器1发送5个ICMP包,但是当成功执行时退出代码为0,错误时则为2。
通常,除了退出代码,插件还会通过stdout(标准输出)提供一行文本信息,Nagios将上述信息作为可读的汇总信息。汇总信息将会全部显示在Web界面相应的状态字段中。对于不喜欢解释退出代码含义的人类而言,这个功能能够很方便地回传服务的相关信息。代码2-2是经过修改后的Ping插件,能够提供一些汇总信息给Nagios。
代码2-2 能够输出汇总信息的Ping插件
#!/bin/sh OUTPUT='ping -c5 server1 | tail -n2' If [ $? -gt 0 ] then echo "CRITICAL!! $OUTPUT" exit 2 else echo "OK! $OUTPUT" exit 0 fi
这次我们使用$OUTPUT变量,组合使用tail命令来获取ping命令输出的最后两行信息。现在,当在Nagios漂亮的Web界面中查看服务信息的时候,在状态信息字段中会显示如下信息:
5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max = 0.1/0.8/3.9 ms
在Nagios 3.0和之后的版本中,插件能够回传多行文本信息,但Nagios依然会将第一行信息显示在Web界面中,而将之后的信息存储在称为“宏”(Macro)的内部数据结构中。
Nagios的这种插件架构的工作方式带来了很多好处,其中之一就是能够通过命令行执行,因为每一个插件都是一个小型的独立程序。“插件开发指南”中特别说明,所有的插件都应当有-h参数,即帮助选项,所以如果想要了解插件如何工作,一般可以通过命令行调用并添加-h参数,这也使得对插件问题的故障诊断易如反掌。如果Nagios在调用某个插件时出现了问题,可以在Shell提示符下直接运行插件,并加入相同的参数,查看具体发生了什么问题。
建议各位读者在修改已有脚本作为Nagios插件前,能够对上述内容有一定了解。当然,读者也可以查看插件开发团队提供的“插件开发指南”,从而作为插件贡献者的一份子,地址是:
http://nagiosplug.sourceforge.net/developer-guidelines.html
2.2.2 远程执行
在第1章1.2节以及前文中曾多次提到,Nagios服务器上运行的插件,以及在被监控主机上远程执行的插件。由于Nagios自身没有办法实现远程执行,所以很有必要了解实际中远程执行的多种实现方式。
前面示例中的那位系统管理员,我们已经很熟悉他了,为了形象理解Nagios在远程服务器上运行插件最简单的方式,我们要再次拜访他。当他需要执行远程功能时,会使用SSH命令。比如说,当他想要查询远程系统的负载平均值时,会执行一条相当简单的命令:
$ ssh server1 "uptime | cut -d: -f4"
SSH客户端会在远程服务器执行命令“uptime | cut -d: -f4”,并将输出回传到本地客户端中(在本例中,回传的信息应当为类似“0.08, 0.02, 0.01” 这样的信息)。这没问题,但是系统管理员希望如果15分钟的平均负载超过3,就给他发送一条短信,于是他编写了代码2-3中的脚本,并上传到了远程服务器。
代码2-3 远程负载平均值检测脚本
#!/bin/sh LOAD='uptime | awk '{print $12}' if [ $LOAD -gt 1 ] then echo "high load on 'hostname' | mail dude@domain.org" fi
在该脚本中,uptime命令的输出使用awk命令进行过滤,从中提取出最后一个数值(15分钟负载平均值)。脚本将此数值与1比较,判断负载是否过高,如果过高,则会向管理员发送一封邮件。当把这个脚本保存为load_checker.sh并存放在远程服务器的/usr/local/bin目录后,管理员就能够通过SSH远程执行,类似于:
ssh server1 "/usr/local/bin/load_checker.sh"
在实际工作中,管理员可能通过cron命令在远程服务器上调度任务定期执行,但这是个测试,各位读者和我动手实验下吧。有意思的是,通过SSH远程执行脚本,SSH不仅会捕获并且回传的内容不仅包括远端脚本的输出,还包括远端脚本的退出代码。
如果系统管理员把他的脚本重写成代码2-4的模样,那他就拥有了一个Nagios插件。
代码2-4 带退出代码的远程负载平均值检测脚本
#!/bin/sh LOAD='uptime | awk '{print $12}' if [ $LOAD -gt 1 ] then echo "Critical! load on 'hostname' is $LOAD" exit 2 else echo "OK! Load on 'hostname' is $LOAD" exit 0 fi
但是Nagios如何执行远端命令,并捕获命令的输出和退出代码呢?难道它只能执行本地硬盘上的程序吗?答案很简单:我们只要编写一个本地插件,使用系统管理员所用的SSH命令就可以了。这个脚本看起来可能与代码2-5中类似。
代码2-5 调用load_checker并重放其输出和退出代码的脚本
#!/bin/sh #get the output from the remote load_checker script OUTPUT='ssh server1 "/usr/local/bin/load_checker.sh"' #get the exit code CODE=$? echo $OUTPUT exit $CODE fi
代码2-5中的脚本没有任何的条件逻辑。它唯一的任务就是执行远端脚本并在本地终端上重放其输出及退出代码。因为它以适当的代码退出并回传了一行文本信息,对于Nagios来说足矣。它作为插件,通过SSH调用其他的插件,但是Nagios不知道这些,也不关心这些,只要插件能够返回退出代码和一些文本信息就足够了。
这种方式是Nagios远程执行工作的基础。通过这种方式,无须在Nagios中构建一套网络协议,Nagios守护进程将这类功能分解成为专用插件,使用这些专用插件反过来配合其他插件通过所需的协议进行通信。
然而,上面介绍使用SSH的方式并不理想。对于新手来说,上面编写的远端插件具有固定的阈值。它会一直检测负载平均值是否大于1,如果有一台日常负载很高的服务器2,需要以不同的阈值检测时,就需要给服务器2再编写一个不同的插件。显然,这种方式扩展性不好,我们需要一种集中的方式来安全地管理阈值。
第二个大问题就是SSH认证。如果Nagios无须提示输入密码就能调用远程执行插件,那么就需要一个认证密钥。除非谨慎地进行了配置,否则该密钥就能在远程服务器上执行任何操作,这将违反最小化特权的原则。我们希望能够明确指定Nagios服务器在每台主机上访问并执行的内容。
这些问题,或者读者们想到的更多问题,都可以通过NRPE(Nagios Remote Plugin Executor,Nagios远程插件执行程序)解决。NRPE分为两部分:在Nagios本地执行的名为check_nrpe的插件,以及在被监控主机上运行的守护进程。守护进程通过诸如xinetd这样的超级服务进程(Super Server)运行,模式类似Windows中的服务,它拥有本地配置文件,其中定义了check_nrep允许访问的信息。用户可以通过配置好的check_nrpe插件访问守护进程,运行预定义的命令,而传递阈值的功能是可选的。守护进程所做的是将客户端输出以及退出代码反过来传递给Nagios。通过NRPE,任何程序只要在守护进程的配置文件中定义,那么它就能够安全地在远程服务器上执行。守护进程可以通过X509协议对客户端进行认证,或者用于传输过程的加密。NRPE是完全跨平台的,所以它可以处理Windows和UNIX客户端上的各种远程执行操作。我们将会在第6章中讲述NRPE的安装和配置,还将介绍一些有意思的替代软件,它们可能更适合运行在读者的环境中。