我們將在這個月嘗試一種略顯激進的方式。一般情況下,我們這個專欄主要采取針對從化名腳本編程人員那里收到的某一常見問題加以解答的方式。而這次,我們將不再沿襲以往做法。取而代之的是,我們將回答一個自己尚未(或至少幾乎未曾)從腳本編程人員那里聽說的問題。
很少有人向我詢問有關WMI事件的問題。這種情況看上去并不正常。WMI的確具備非?!翱帷钡墓δ芴匦?-或許多少有些復雜--但迄今為止,我們尚未收到過有關它的任何問題。這種情況是否出于廣大專業人員對WMI所具備的事件處理能力尚不熟悉的緣故,亦或出于從未有人向您介紹過有關情況,而您也沒有碰巧讀到過合適的書籍?
好吧,就算情況的確如此,而本月的專欄文章則將圍繞這一主題向您進行簡要介紹。盡管您應可憑借這篇專欄文章蹣跚學步,并了解有關WMI事件的些許皮毛,然而,我們仍希望您至少對WMI事件的常規工作方式具備最基本的認識,這將對您大有幫助。如果您需要在繼續閱讀本文之前先對WMI進行一次速成式學習,那么,我們便強烈建議您選用位于MSDN的WMI入門指南系列教材;您只需閱讀該系列教材的第一部分,即可掌握與事件有關的入門知識,并為繼續學習事件技術奠定良好基礎。
好的,在我們開始學習WMI事件之前,或許應就所謂“事件”的含義達成共識。事件是指那些發生在計算機環境內部的對象。實際上,那些只是潛在的事件;而當您對某一事物的發生給予關注時,它才算的上真正發生,而這就是一個事件。
簡而言之,WMI事件正是您所關注對象--也就是說,您所需獲得通知的對象--已經發生的通知。舉例來說,您也許希望在Web服務器的處理器使用總體比率超過90%這一閾值時接到有關通知,以便設置一定數量的間歇。或許您還希望在本公司文件服務器總存儲容量占用率低于10%的情況下接到相關通知。而WMI事件則是一種由WMI提供的機制,可幫助您借助某一特定腳本針對系統變化進行相應配置,執行接收操作,并做出必要響應。
而針對WMI加以理解的另一種方法則是,WMI事件對于WMI來說,就如同警報信息對于性能監視器、陷阱對于SNMP和規則對于Microsoft操作管理器(MOM)所具有的意義。以上四組關系代表著針對系統和(或)網絡變化進行監視或做出反應的具體方式。
話已經說得足夠多了?,F在讓我們開始編寫腳本。以下腳本主要用來針對基于本地計算機(也就是您賴以運行腳本的計算機)的進程實施監控。而該腳本所尋找的事件則是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()
腳本一旦收到有關事件發生情況的通知,便會越過暫?;蜃钄啻a行,繼續運行隨后出現的指令。而隨后出現的指令則是您針對相關通知所應做出的響應。在這個示例中,我們只需讓用戶知道事件通知已被收到即可。
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