2009年6月12日金曜日

Windows PowerShell でイベントログをリアルタイム監視

The PowerShell Guy が教えてくれた、WindowsServerでイベントログをリアルタイムで監視する方法。
 
 


.Net FrameWorkで最新のイベントログをキャッチ


.Net FrameWork を使えるPowerShellなら、色々楽勝...といっても結局はWMIに問い合わせるみたい、某所で使っているイベントログ監視スクリプトはVBSで作ってあるけど、あれもWMIだったな。
 

ただ、system.management.ManagementEventWatcher クラスをいきなり使えるということでだいぶ違うように見える。
実はクラスとかあまり理解してないが、なんとも便利になったと思う。
 
 

PowerShellプロンプトでやってみる


イベントを待つには3行ですっきりOK、表示用にもう一行。
手っ取り早く効果を試せるので、下記をPSのプロンプトに張り付けてみる。

[sourcecode language='sh']$ew = new-object system.management.ManagementEventWatcher
$ew.query = "Select * From __InstanceCreationEvent Where TargetInstance ISA 'Win32_NTLogEvent'"
$e = $ew.WaitForNextEvent()
$e[/sourcecode]

ManagementEventWatcher パブリック メソッド の WaitForNextEvent() を使っている、張り付けたスクリプトはいったんここで止まる。
 

PS C:\>$ew = new-object system.management.ManagementEventWatcher
PS C:\>$ew.query = "Select * From __InstanceCreationEvent Where TargetInstance ISA 'Win32_NTLogEvent'"
PS C:\>$e = $ew.WaitForNextEvent()
PS C:\>$e
_←点滅カーソル


何かイベントが発生するまで待機するので、他のシェルからテスト用に eventcreate コマンドでイベントログを書き込み。
 

C:\>EVENTCREATE /T ERROR /ID 1000 /L APPLICATION /D "wait test"
 
成功: 種類が 'ERROR' のイベントが、'APPLICATION' ログ内に、'EventCreate' をソースとして作成されました。

 
すると、 $e に発生したイベントのオブジェクトが代入され、 直後で指定しているので $e が表示される
 

はい出た。
__GENUS : 2
__CLASS : __InstanceCreationEvent
__SUPERCLASS : __InstanceOperationEvent
__DYNASTY : __SystemClass
__RELPATH :
__PROPERTY_COUNT : 3
__DERIVATION : {__InstanceOperationEvent, __Event, __IndicationRelated, __SystemClass}
__SERVER :
__NAMESPACE :
__PATH :
SECURITY_DESCRIPTOR : {1, 0, 20, 128...}
TargetInstance : System.Management.ManagementBaseObject
TIME_CREATED : 128892011594751253

 

が、えらくメタな情報だな。
 
 

今回目的のイベントログは TargetInstance ってプロパティに格納されているので表示する、この辺はWMI。
PS C:\> $e.targetinstance
 
 
__GENUS : 2
__CLASS : Win32_NTLogEvent
__SUPERCLASS :
__DYNASTY : Win32_NTLogEvent
__RELPATH : Win32_NTLogEvent.Logfile="Application",RecordNumber=13539
__PROPERTY_COUNT : 16
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
Category : 0
CategoryString :
ComputerName : ********
Data :
EventCode : 1000
EventIdentifier : 1000
EventType : 1
InsertionStrings : {wait test}
Logfile : Application
Message : wait test
RecordNumber : 13539
SourceName : EventCreate
TimeGenerated : 20090********.000000-000
TimeWritten : 20090********.000000-000
Type : エラー
User : ********\sawano

 
OK、イベントソース、コードなど、おなじみのものが表示されている。
 
 



監視をループさせる


それではイベントログをリアルタイムで監視させる。
特に芸も無く、ループで回すだけだ。
[sourcecode language='sh']$a = 0

$ew = new-object system.management.ManagementEventWatcher
$ew.query = "Select * From __InstanceCreationEvent Where TargetInstance ISA 'Win32_NTLogEvent'"

do
{
$e = $ew.WaitForNextEvent()
$e.TargetInstance
}
while ($a -ne 1)
[/sourcecode]

While にずっと達成できない条件を指定して、ずっと回ってもらう。
 
これをPSプロンプトに流すと、Whlieの後で、カーソル点滅。 最後はDoの>>が消えるまでEnterの入力が必要。
 

--snip--
>> $e.TargetInstance
>> }
>> while ($a -ne 1)
>>
_←点滅カーソル

 

さて、この状況でほっといてみよう、EventCreateで試してもいい。
Vistaでやっていたら、意外と色々ログが上がって来て面白かった。
 
 

おわりに


さて、これをやってどうするか。
イベントをキャッチして、mixi や wassr に投稿するBotも捨てがたいが、通常は警告(Warning)、エラー(Error)もしくは特定のイベント発生を管理者に通知したい。
手段として妥当なところでは、メールだろうか。
 

今度はメール通知部分をくっつけてみよう、起動はタスクマネージャからだな。