前兩天接到一個需求,要求對現有網域中的关键业务主機進行時鐘監控,若發現時鐘偏移超過規定秒數則自動發警告给管理员。

阅读微软官方的NTP服务相关文档得知,windows网域环境中维持每台客户端主机与DC之间时钟同步的一个关键服务就是w32time,我们在cmd下下如下指令可以看到:

关于时钟同步的原理这里就不多讲了,反正最终所有网域主机其实都是与域中的根PDC进行同步。在上面的输出中我们可以看到指定主机的时钟与本地主机间的时钟时差为+0.0109190s,关键点来了。试想,如果能将指令中的computers指向根PDC(这个不难做到),然后将此命令输出内容中的时差值抓取出来与我们自定的时钟偏移阈值进行比较,超过则告警(透过Nagios邮件、短信等),反之则显示正常。这样问题不就明了:如有哪一台主机的w32time服务未正常启动,或启动了但未发挥作用让时钟自动与PDC同步,那么就会造成时差,当时差超过某个点时就告警。

想到了我们就开干,由于之前用过一段时间vbs,能写一小点vbs脚本,故找出vbs参考手册,查以下以下几个关键点:

1、如何从用vbs截取出cmd命令的输出内容?

2、如何从指定内容中搜寻出需要的字符串?如上图我们要在w32tm命令的输出中找出时差值。

3、如何让vbs读取我们设定的参数列?Nagios中配置命令时需要。

4、如何设定Nagios和NSClient将vbs脚本的执行结果传回Nagios并触发警告?

以上是大的思考方向。

下面给出我的解决方法,不讲原理,只写步骤,因为原理太多了,本人口拙,一两句说不清楚。

我用的环境是CentosNagios-3.xNSClient-0.4.1.101windows基本所有版本都有

注意:对于win7以前的系统比如xp,win2003和以后如win2008R2,此w32tm的用法会稍有不同的,建议用之前先w32tm/?一下看看帮助文档。

1、google上找到一个check_time.vbs的脚本,弄下来研究了一下,基本符合我们上面的需求,稍加改写:

源码下载地址,源码对win7前的系统兼容有问题,就是上面提到的注意。

改写后:将下面代码拷贝下来,另存为check_time.vbs文件,以下代码对win7前后系统均兼容。

Set Args = WScript.ArgumentsIf WScript.Arguments.Count < 3 ThenErr = 3WScript.Echo "check_time.vbs V1.01"WScript.Echo "Usage: cscript /NoLogo check_time.vbs serverlist warn crit [biggest]"Wscript.Echo ""Wscript.Echo "Options:"Wscript.Echo " serverlist (required): one or more server names, coma-separated"Wscript.Echo " warn (required): warning offset in seconds, can be partial"Wscript.Echo " crit (required): critical offset in seconds, can be partial"Wscript.Echo " biggest (optional): if multiple servers, else use default least offset"Wscript.Echo ""Wscript.Echo "Example:"Wscript.Echo "cscript /NoLogo check_time.vbs myserver1,myserver2 0.4 5 biggest"Wscript.Quit(Err) '如果參數數量小于3,則返回錯誤碼Err=3End Ifserverlist = Args.Item(0) ' one or more server names, coma-separatedwarn = Args.Item(1) ' warning offset in seconds, can be partialcrit = Args.Item(2) ' if multiple servers, else use default least offsetIf WScript.Arguments.Count > 3 Thencriteria = Args.Item(3)Elsecriteria = least '等于3則取最小值End IfSet objShell = CreateObject("Wscript.Shell")strCommand = "%SystemRoot%\System32\w32tm.exe /monitor /computers:" & serverlistset objProc = objShell.Exec(strCommand)input = ""strOutput = ""Do While Not objProc.StdOut.AtEndOfStreaminput = objProc.StdOut.ReadLineIf InStr(input, "NTP") Then 'input中不包含“NTP”字符串,則InStr返回值0,跳到End IfstrOutput = strOutput & inputEnd IfLoopSet myRegExp = New RegExpmyRegExp.IgnoreCase = TruemyRegExp.Global = TruemyRegExp.Pattern = " NTP: ([+-][0-9]+\.[0-9]+)s"Set myMatches = myRegExp.Execute(strOutput)result = ""If myMatches(0).SubMatches(0) <> "" Thenresult = myMatches(0).SubMatches(0)End IfFor Each myMatch in myMatchesIf myMatch.SubMatches(0) <> "" ThenIf criteria = "biggest" ThenIf abs(result) < Abs(myMatch.SubMatches(0)) Thenresult = myMatch.SubMatches(0)End IfElseIf abs(result) > Abs(myMatch.SubMatches(0)) Thenresult = myMatch.SubMatches(0)End IfEnd IfEnd If' Wscript.Echo myMatch.SubMatches(0) & " -debug"NextIf result = "" ThenErr = 3Status = "UNKNOWN"ElseIf Abs(result) > Abs(crit) ThenErr = 2status = "CRITICAL"ElseIf Abs(result) > Abs(warn) ThenErr = 1status = "WARNING"ElseErr = 0status = "OK"End IfWscript.Echo "NTP " & status & ": Offset " & result & " secs|offset=" & result & "s;" & warn & ";" & crit & ";"Wscript.Quit(Err)

2、将上面的check_time.vbs脚本放到NSClient安装目录的:

C:\Program Files\NSClient++\scripts\lib

3、修改NSClient的配置文件nsclient.ini,加上以下内容:

[/settings/external scripts/scripts]timevbs = cscript.exe //T:30 //NoLogo scripts\\lib\\check_time.vbs 10.40.1.190 5 10

这个配置文件的写法还是很讲究的,此处花了我相当多的时间进行调试,汗。最终官网找到以下两篇文章,参考解决:

http://nsclient.org/nscp/wiki/CheckExternalScripts

http://www.nsclient.org/nscp/discussion/topic/1079

4、写一个vbs脚本,每台主机上执行脚本后就会自动拷贝修改好的nsclient.ini和check_time.vbs到指定目录。当然可以批量派发执行。

Dim fsoSet fso = CreateObject("Scripting.FileSystemObject")fso.CopyFile "\\10.40.1.129\ShareFolder\Linux\check_time.vbs","C:\Program Files (x86)\NSClient++\scripts\lib\",Truefso.CopyFile "\\10.40.1.129\ShareFolder\Linux\nsclient.ini","C:\Program Files (x86)\NSClient++\",True'对于32位的系统,此路径设置会稍有不同Set objShell = CreateObject("Wscript.Shell")objShell.Run"cmd /k net stop nscp && net start nscp",vbhide

5、以上都是针对被监控端进行的配置,完成后我们建议先到Nagios中进行测试,如下

[root@pcnnagios libexec]# ./check_nrpe -H 10.40.1.106 -c timevbsNTP OK: Offset -0.3144475 secs|'offset'=-0.31444s 'Warning'=5 'Critical'=10

没问题,可以看到测试OK,输出结果也符合我们vbs脚本编写的预期。

6、万事俱备,那下面就该进行Nagios的命令和服务配置了,此处直接贴配置,细节上可以因人而异进行微调。

command.cfg内添加以下:

# 'check_time' command definitiondefine command{command_name check_timecommand_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c timevbs}

service.cfg下添加以下:

define service{use generic-service,srv-pnphostgroup_name windows-serversservice_description Check Time Synccheck_command check_time}

7、以上所有步骤弄完后,可以到我们的Nagio服务监控界面检验成果了,

如上service.cfg的配置中,我们有设定用pnp4nagios进行绘图:

8、扩散一下思维:参考此方法,那么我们以后想透过nagios利用Windows中的脚本,如vbs、bat、powershell等监控windows主机的其他应用或功能也水道渠成了。前提是要会写对应功能的脚本,至少要看得懂吧。。。