赢在执行

这个世界上只有两样东西愈分享愈多,那就是智慧与爱。

BlogJava 首页 新随笔 联系 聚合 管理
  17 Posts :: 11 Stories :: 13 Comments :: 0 Trackbacks

我们将在这个月尝试一种略显激进的方式。一般情况下,我们这个专栏主要采取针对从化名脚本编程人员那里收到的某一常见问题加以解答的方式。而这次,我们将不再沿袭以往做法。取而代之的是,我们将回答一个自己尚未(或至少几乎未曾)从脚本编程人员那里听说的问题。

很少有人向我询问有关WMI事件的问题。这种情况看上去并不正常。WMI的确具备非常“酷”的功能特性--或许多少有些复杂--但迄今为止,我们尚未收到过有关它的任何问题。这种情况是否出于广大专业人员对WMI所具备的事件处理能力尚不熟悉的缘故,亦或出于从未有人向您介绍过有关情况,而您也没有碰巧读到过合适的书籍?

好吧,就算情况的确如此,而本月的专栏文章则将围绕这一主题向您进行简要介绍。尽管您应可凭借这篇专栏文章蹒跚学步,并了解有关WMI事件的些许皮毛,然而,我们仍希望您至少对WMI事件的常规工作方式具备最基本的认识,这将对您大有帮助。如果您需要在继续阅读本文之前先对WMI进行一次速成式学习,那么,我们便强烈建议您选用位于MSDN的WMI入门指南系列教材;您只需阅读该系列教材的第一部分,即可掌握与事件有关的入门知识,并为继续学习事件技术奠定良好基础。

好的,在我们开始学习WMI事件之前,或许应就所谓“事件”的含义达成共识。事件是指那些发生在计算机环境内部的对象。实际上,那些只是潜在的事件;而当您对某一事物的发生给予关注时,它才算的上真正发生,而这就是一个事件。

简而言之,WMI事件正是您所关注对象--也就是说,您所需获得通知的对象--已经发生的通知。举例来说,您也许希望在Web服务器的处理器使用总体比率超过90%这一阈值时接到有关通知,以便设置一定数量的间歇。或许您还希望在本公司文件服务器总存储容量占用率低于10%的情况下接到相关通知。而WMI事件则是一种由WMI提供的机制,可帮助您借助某一特定脚本针对系统变化进行相应配置,执行接收操作,并做出必要响应。

而针对WMI加以理解的另一种方法则是,WMI事件对于WMI来说,就如同警报信息对于性能监视器、陷阱对于SNMP和规则对于Microsoft操作管理器(MOM)所具有的意义。以上四组关系代表着针对系统和(或)网络变化进行监视或做出反应的具体方式。

话已经说得足够多了。现在让我们开始编写脚本。以下脚本主要用来针对基于本地计算机(也就是您赖以运行脚本的计算机)的进程实施监控。而该脚本所寻找的事件则是notepad.exe进程的创建。如需对这个脚本加以试用,则请将其输入记事本,并保存为MonitorNotepad.vbs。接着,打开一个命令行窗体,并导航至保存有下列脚本的目录,然后,输入C:\scripts>cscript MonitorNotepad.vbs。

strComputer = "."

Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")

strWQL = "SELECT * " & _
         "FROM __InstanceCreationEvent " & _ 
         "WITHIN 2 " & _
         "WHERE TargetInstance ISA 'Win32_Process' " & _
         "AND   TargetInstance.Name = 'notepad.exe'"

WScript.Echo "Waiting for a new instance of Notepad to start..."
Set objEventSource = objWMIService.ExecNotificationQuery(strWQL)
Set objEventObject = objEventSource.NextEvent()
WScript.Echo "A new instance of Notepad was just started."

在脚本运行过程中,您将会看到如下图所示的情况出现:


如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。

如果您接着运行了一个新的记事本实例,该脚本便会做出如下反应:


如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。

如图所示,您目前已具备了针对记事本进程实施监控的能力。而这种能力将有助于您避免长达数小时的无效劳动,难道不是吗?好吧,或许情况还不致于此。但事实却是,您可在任何具备WMI支持特性的计算机设备上利用与上述脚本相似的其它脚本针对任何由WMI负责管理的资源实施监控,从这个角度来看,事件脚本则可帮助您避免长达数小时的无效劳动。

试想您拥有一台非常繁忙的企业内部网络服务器,并在此基础上进一步假设您的企业Web开发部门偶尔会将某些有害代码发布至上述企业内部网络服务器,而这些有害代码则可能莫名其妙地设法杀死相关Web服务。每当有Web服务终止,您的用户便会有所反应。而首当其冲的修复方法(尽管只能应付燃眉之急)则是重新启动刚刚遭到终止的Web服务。如果您能够以自动化方式完成上述处理过程,那将是一种相当有用的功能特性。下列脚本为您展示了实现上述功能的具体方法。该脚本将针对遭到终止的Web服务进行检测,并试图重新启动相关服务。请在您键入该脚本的过程中注意分辨它与前面那个记事本监控脚本的区别所在。

StrComputer = “.”
Set objWMIService = GetObject(“winmgmts://” & strComputer & “/root/cimv2”)
strWQL = “SELECT * “ & _
         “FROM __InstanceModificationEvent “ & _ 
         “WITHIN 2 “ & _
         “WHERE TargetInstance ISA ‘Win32_Service’ “ & _
         “AND   TargetInstance.Name = ‘w3svc’” & _
         “AND   TargetInstance.State = ‘Stopped’”
Set objEventSource = objWMIService.ExecNotificationQuery(strWQL)
Wscript.Echo “Monitoring the web service…”
Set objEventObject = objEventSource.NextEvent()
Wscript.Echo “The web service just stopped.”

为亲身体验上述脚本的运行效果,请将其键入记事本界面,并保存为MonitorWeb.vbs。接下来,应确保W3SVC服务在本地计算机上处于运行状态(使用net start w3svc命令将是一种非常有效的方法)。然后,在一个命令行窗体内键入C:\scripts>cscript MonitorWeb.vbs,以便开始运行该脚本。于是,您便会看到如下图所示的情况出现:


如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。

接下来,请打开另一个命令行窗体,并通过键入C:\>net stop w3svc的方式终止相关Web服务。而该脚本则应注意到相关Web服务已被终止,并为您显示一条相关信息:


如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。

在这一时点,该脚本仅仅使用了下面这行代码即已侦测到Web服务已被终止:

WScript.Echo "The web service just stopped."

这行代码主要用来显示一条相关信息;当然,您还可通过添加代码的方式轻而易举地实现Web服务重启,并为确保重启功能有效而再次执行检查,同时,发送给您一封针对已发生所有事件加以简要概括的电子邮件。那些曾浏览过“脚本漫谈”专栏开篇文章的读者将可借助Run或Exec方法轻而易举地运行“net start w3svc”命令。而那些已通过查阅WMI入门系列读物方式深入钻研过WMI的朋友则可运用WMI实现相关服务的重新启动。在任何情况下,这种操作都将是非常直截了当的。下面提供了一个利用Run方法达到上述目的的示例脚本:

strComputer = "."

Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")

strWQL = "SELECT * " & _
         "FROM __InstanceModificationEvent " & _ 
         "WITHIN 2 " &_
         "WHERE TargetInstance ISA 'Win32_Service' " & _
         "AND   TargetInstance.Name = 'w3svc'" & _
         "AND   TargetInstance.State = 'Stopped'"

Set objEventSource = objWMIService.ExecNotificationQuery(strWQL)

WScript.Echo "Monitoring the web service..."
Set objEventObject = objEventSource.NextEvent()

WScript.Echo "Web service just stopped....waiting for a few seconds."
WScript.Sleep(5000)
WScript.Echo "Attempting to restart the web service using the net.exe tool."

Set objShell = CreateObject("WScript.Shell")
objShell.Run "%COMSPEC% /c net start w3svc",,1
WScript.Echo "Restarted the web service"

如需尝试运行上述脚本,请务必确保相关Web服务(w3svc)正处于运行状态,并在此基础上执行该脚本。一旦脚本显示如下信息:Monitoring the web service…(正在对Web服务进行监视……),就请打开第二个命令行窗体,并通过键入type C:\>net stop w3svc的方法终止相关服务。而该脚本则应觉察到相关Web服务已被终止,接着,脚本将暂停几秒钟,以确保服务关闭操作执行完毕,然后,脚本将通过发出net start w3svc指令的方式重新启动相关服务。下图展示了上述脚本在执行过程中所输出的信息:


如果您所使用的浏览器无法支持嵌入式框架,请, 点击此处 以便在单独页面中进行浏览。

令人充满希望的是,您即将开始对某些问题隐患给予关注。如果您的确希望如此,便有可能对有关上述某一脚本的逐行解释抱有兴趣--而这恰恰是我们即将在本月中全力提供的信息服务内容。

脚本代码行:

strComputer = "."

仅仅用来将您执行相关操作所需依托的计算机名称存储于当前脚本的下一行。引号中的圆点(“.”)表示“使用本地计算机”。如果您目前正处在某一网络环境下,而自己又是基于附近另一台计算机的本地管理员,则可尝试将strComputer变量设定为自己所使用的计算机名称(例如,strComputer = “WebServer01”)--也就是说,用当前计算机名称替换圆点。这样一来,监控脚本便可基于自身实际运行所依托的远程计算机(而非本地计算机)执行监控操作。

脚本代码行:

Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")

创建一个通往WMI服务的连接,并将针对该连接的引用保存于objWMIService变量。事实上,这行代码具有一定的超前作用,并为上述连接指定了一个专用WMI名称空间--即/root/cimv2名称空间。您可将所谓名称空间当作某些类似于文件夹的事物看待。所不同的是,文件夹仅供用来将一系列特定文件组织在一起,而WMI名称空间则可实现一整套WMI类的有机结合。/root/cimv2名称空间恰好同时存放着Win32_Service WMI类和Win32_Process WMI类,因此,可供在我们设定的全部示例中加以应用。事实上,/root/cimv2名称空间存储着关系到系统管理利弊得失的绝大多数WMI类--因此,您会经常在自己的脚本中看到它并使用它。只要您接触到这个名称空间,我们便可告诉您cimv2位所代表的含义--它是Common Information Model, version 2(通用信息模型2.0版)的缩写。如果您有兴趣了解与这一名称起源有关的更多信息资料以及WMI自身的历史渊源,就请做好悉心读书的准备,并回头访问分布式管理任务团队(DMTF)网站。

接下来的一系列代码行主要用来构成一个WMI Query Language(WMI查询语言,WQL)查询。由于这种特殊查询方式主要被用来启动事件监控程序,因此,经常被人们当作事件通知查询加以运用。如果您对SQL较为熟悉,便会觉得这种查询方式与之大同小异。如果您对SQL也不甚了解,照样不必担心,您只需对这种查询中部分元素所引用的对象加以理解把握,以便在需要时对它们进行相应修改,从而,达到调整查询内容的目的。

第一个重要的代码位是__InstanceModificationEvent。它将可被修改成__InstanceCreationEvent或__InstanceDeletionEvent。所幸有一点非常明确,举例来说,将这个代码位修改成__InstanceDeletionEvent的做法会导致脚本放弃对调整事件的监视,转而对删除事件进行监控。

WITHIN 2子句主要用来以秒为单位就某项资源的轮询事件发生频率加以设定。每隔两秒对某一对象进行一次检查的做法在大多数情况下或许略显频繁,但我们在示例中设定这一频率的目的无非是希望产生一种快捷直观的效果。

ISA ‘Win32_Service’子句主要针对用以指代您所需监控对象的WMI类进行设定。如果您对有关WMI类的知识不甚了解,就请访问MSDN网站,并阅读WMI入门文章。如果您需要查找可供加以应用的WMI类,则应下载Scriptomatic,并对其加以试用。

.Name = ‘w3svc’和.State = ‘Stopped’子句仅仅是用来将监控对象局限于某项特定资源的属性设定代码--在这个示例中,我们为Win32_Service指定了一个等于‘w3svc’的Name(名称)属性和一个等于‘Stopped’的State(状态)属性。

StrWQL = “SELECT * “ & _
         “FROM __InstanceModificationEvent “ & _ 
         “WITHIN 2 “ & _
         “WHERE TargetInstance ISA ‘Win32_Service’ “ & _
         “AND   TargetInstance.Name = ‘w3svc’” & _
         “AND   TargetInstance.State = ‘Stopped’”

接下来的代码行旨在通过运行通知查询的方式从实际上启动监视进程。

Set objEventSource = objWMIService.ExecNotificationQuery(strWQL)

编写这个代码行的目标仅仅在于将监视进程已经开始的情况告知用户。

Wscript.Echo “Monitoring the web service…”

下一个代码行的作用较为重要。它将使脚本处于暂停状态,直到程序接收到下一个事件。相关操作将在这个控制点中止,而脚本的后续部分直到已被我们设定为监控对象的事件发生并已向我们发出通知的时候才会继续运行。

Set objEventObject = objEventSource.NextEvent()

脚本一旦收到有关事件发生情况的通知,便会越过暂停或阻断代码行,继续运行随后出现的指令。而随后出现的指令则是您针对相关通知所应做出的响应。在这个示例中,我们只需让用户知道事件通知已被收到即可。

WScript.Echo "The web service just stopped."

这种技巧也许在某些特定情况下具有实用价值,但更多时候,您往往更需要在这个控制点执行某项特殊操作。

到此为止,您已掌握了必要的知识技能--也就是说,我们已将WMI事件初步介绍给您。虽然我们讨厌成为cliché,但是,您在某些情况下将不得不为从事脚本编写工作的同僚多付出一些周折:“我们只不过刚刚接触到这种具备较高实用价值的管理技术的皮毛”。这也就是说,我们希望自己已在此为您提供了足够的信息资料,而您则可借助这些信息资料围绕将WMI事件处理功能应用于自身所处工作环境的具体实现方式展开思考。下个月,我们将继续深入探讨本文所涉及的内容,并希望针对广大读者围绕本文所提出的疑难问题加以解答。还是那句老话,如果您针对本文产生了某些非常“酷”并(或)具有实用价值的想法,就请来信告知我们。

我们衷心希望您渡过一个安全而愉快的假期。

脚本专家组

以上便是我们本月呈献给您的全部篇幅。如果您需要提出任何问题或发表任何评论,敬请致电mailto:%20scripter@microsoft.com?Subject=Tales from the Script - January 2003


原文具体链接:http://www.microsoft.com/china/technet/columns/scripts/sg0103.asp

posted on 2007-03-20 00:13 飛雪(leo) 阅读(619) 评论(0)  编辑  收藏 所属分类: 其他方面

只有注册用户登录后才能发表评论。


网站导航: