2011年3月11日金曜日

◆イベントログを取得(抽出)する(Get-WinEvent)

イベントログを取得するにはGet-WinEventコマンドレットを使えば良い。
取ってきたログを抽出するのも普通にやれば問題ないのだが、全部取ってきてからでは時間が掛かる。

そんな時は、ログを取ってくる時点でFilterして上げれば良い。FilterHashtableオプションを使うのが簡単そうだ。

サンプルとして過去数カ月の発生頻度の高いエラーや警告をサマリーして抽出するスクリプトを作ってみた。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020

$levels = @{重大 = 1 ; エラー =2 ; 警告 = 3}
$lognames = "system","application"
$month = 10  #過去何ヶ月を表示するか

function getevent($logname,[ref]$reflevel
){
 
$level = $reflevel.
value
 
Write-Host <$logname $level.name -ForegroundColor Cyan
  Get-WinEvent -ErrorAction SilentlyContinue -FilterHashtable
 @{
    level 
= $level.
value
    logname 
= $logname
    starttime = ((get-date).addmonths(-$month
))
  } 
|
 
 
group id | sort count -des | select -first 5 |
 
 
select count,name,{$_.group[0].message} | ft -auto -Wrap
}

$lognames | %
{
 
$logname = $_
  $levels.GetEnumerator() | sort value | %{getevent $logname ([ref]$_) }
}

結果はこんな感じになる。
20110311105207

指定できる抽出条件は以下のような感じ。

20110311105655

また、Get-WinEventコマンドレットはコンピューター名も指定できるようなので、ドメイン管理者とかであれば、複数サーバーを巡回させてSystemCenter的な使い方もできそうだ。

---- 2015/3/3 --

Ver3以上であればHashTableからPSCustomObjectに変換して以下の様な感じでもOK
(本質的な部分ではないのでどうでもよいのだが、[ref」でやるのはちょっとイマイチな感じもあるので、個人的にメモしておく)
--

あっれー、違うっぽい?「PsCustomObject」は不要で、単に配列にしたからEnumerate不要になっただけ?

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021

$levels = [PsCustomObject]@{name="重大";value=1},
          [PsCustomObject]@{name="エラー";value=2},
          [PsCustomObject]@{name="警告";value=3}
$lognames = "system","application"
$month = 10  #過去何ヶ月を表示するか

function getevent($logname,$level
){
 
Write-Host <$logname $level.name -ForegroundColor Cyan
  Get-WinEvent -ErrorAction SilentlyContinue -FilterHashtable
 @{
    level 
= $level.
value
    logname 
= $logname
    starttime = ((get-date).addmonths(-$month
))
  } 
|
 
 
group id | sort count -des | select -first 5 |
 
 
select count,name,{$_.group[0].message} | ft -auto -Wrap
}

$lognames | %
{
 
$logname = $_
  $levels | sort value | %{getevent $logname ($_) }
}

5 件のコメント:

  1. ホストコンピュータからのオープン化に伴い、COBOL大陸から追放され、PowerShellの世界に踏み込み始めた社内SEです。記事参考になりました。

    返信削除
  2. すごい。洗練されたコードです。
    参考になります。
    17行目からの使い方は思いつきませんでした。

    返信削除
  3. お役に立てて嬉しいです。
    私自身もだいぶ忘れていたので見直すきっかけになりました。
    ありがとうございます。

    返信削除
  4. このpowershelを探してました。
    ・ログの日付を出すことは可能ですか?
    また、複数のコンピュータを対象にすることは可能ですか?
    ご指南をいただきたい

    返信削除
  5. Get-WinEvent が返してくるオブジェクトはTimeCreatedプロパティを持っていますのでそれが使えるのではないでしょうか。
    Get-WinEvent -LogName system -MaxEvents 2
    とかやると表示が確認できると思います。
    また、Get-WinEventはComputerNameプロパティを持っていますのでコンピューター名を指定して巡回するような事もできそうです。
    雰囲気は以下の様な感じでしょうか。
    "ho-pc","ge-pc" | %{Get-WinEvent -LogName system -MaxEvents 2 -ComputerName $_}
    当然それぞれのPCへのアクセス権が必要になります。

    返信削除