PowerShell で Windows イベント ログ データを取得する – 知っておくべきこと
Windowsイベントログの仕組みに慣れていないと、この一連の作業は頭痛の種になることがあります。数百、数千ものログを精査した経験があれば、内蔵のイベントビューアーがいかに遅くて扱いにくいかご存知でしょう。さらに、プロセスを自動化したり、リモートサーバーから特定の情報を取得したりするだけで、手間が大幅に省けることもあります。そこでPowerShellのGet-WinEventの出番です。より柔軟で高速、そして特に大規模なマシンや複数のマシンでログを精査する際には、まさに命綱となる存在です。この記事では、Get-WinEventの機能を活用し、効率的にフィルタリングし、長時間待つことなく必要な情報を取得する方法を学びます。
PowerShellでイベントログを検索する方法
Get-WinEventを使用してログを直接アクセスする
まず、PowerShell を管理者として実行していることを確認してください。そうしないと、セキュリティログなどの特定のログが表示されなくなるなど、問題が発生します。管理者権限があれば、アプリケーションログなどから最近のイベントを取得するのは簡単です。
Get-WinEvent -LogName Application -MaxEvents 20
非常に基本的な機能ですが、何が起こっているかを確認するのに効果的です。もっとログが欲しいですか?追加するだけで、-ListLog *利用可能なすべてのログが表示されます。例えば、リモートデスクトップ接続イベントを確認したい場合は、Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operationalログを参照してください。
Get-WinEvent -LogName Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
Windows で OpenSSH を実行している場合、SSH ログも同様です。
Get-WinEvent -LogName OpenSSH/Operational
システムやアプリケーションなどの複数のログにわたってエラーや警告を探していて、過去 1 日間のログのみが必要な場合は、フィルターを組み合わせます。
$StartDate = (Get-Date) - (New-TimeSpan -Days 1) Get-WinEvent -LogName Application, System | Where-Object { ($_. LevelDisplayName -eq "Error" -or $_. LevelDisplayName -eq "Warning") -and $_. TimeCreated -ge $StartDate }
マシン名、タイムスタンプ、イベントID、ユーザー情報など、特定のフィールドだけを抽出したいですか?出力をパイプで指定しますFormat-Table。
Get-WinEvent -LogName System | Format-Table Machinename, TimeCreated, Id, UserID
あるいは、何らかの理由でユーザー名を SID に変換するには、次のようなプロパティを追加します。
Get-WinEvent -FilterHashtable @{LogName='System'} | Select-Object @{Name="Computer";Expression={$_.machinename}}, @{Name="UserSID";Expression={$_. UserId. Translate([System. Security. Principal. NTAccount]).Value}}, TimeCreated
FilterHashtable によるイベント検索の高速化
ここからが少し「プロっぽい」話になります。Where -Objectを使ってフィルターをマージする方法は確かに機能しますが、大量のログを処理する場合は非常に遅くなります。代わりに、Get-WinEventにFilterHashtableパラメータを使ってフィルター対象を直接指定することで、処理速度を大幅に向上させることができます。これは、Windowsに必要なものを正確に伝え、余計な処理を省くようなものです。
違いを測定してみましょう。過去 30 日間のエラーと警告が必要だとします。
$StartDate = (Get-Date).AddDays(-30) # Slow way — uses Where-Object Measure-Command { Get-WinEvent -LogName Application, System | Where-Object { ($_. LevelDisplayName -eq "Error" -or $_. LevelDisplayName -eq "Warning") -and $_. TimeCreated -ge $StartDate } } # Faster way — using FilterHashtable Measure-Command { Get-WinEvent -FilterHashtable @{LogName='System', 'Application'; Level=2, 3; StartTime=$StartDate} }
ほとんどの設定では、FilterHashtable アプローチの方がはるかに高速で、実行時間を大幅に短縮できます(1分以上から数秒に短縮されるなど)。もちろん、可能な場合はフィルターを組み合わせてください。例えば、特定のイベントIDを探している場合は、id=1234ハッシュテーブルを追加するだけです。
Get-WinEvent -FilterHashtable @{LogName='System'; ID=1074} | Format-Table TimeCreated, Id, Message
この種のフィルターは、無関係なエントリを無視することなく、シャットダウン イベント、再起動ログ、ログイン失敗など、必要な情報を正確に特定するのに役立ちます。
FilterXml による高度なフィルタリング
フィルタリングのニーズが複雑な場合、FilterHashtable だけでは不十分な場合があります。そこで、複雑な複数条件検索を可能にする魔法のXMLクエリ言語、FilterXml を使います。少しオタクっぽく聞こえるかもしれませんが、イベントビューアーのグラフィカルインターフェースを使ってこれらのクエリを作成したり、既存のクエリを再利用したりできます。
簡単な例を以下に示します。過去 1 か月間のシステム ログから最新の重大なエラーを取得します。
$xmlQuery = @' <QueryList> <Query Id="0" Path="System"> <Select Path="System"> *[System[(Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) <= 2592000000]]] </Select> </Query> </QueryList> '@
次のコマンドで実行します:
Get-WinEvent -FilterXML $xmlQuery
イベントビューアーからXMLクエリを直接コピーするには、 を実行しeventvwr.msc、ログをフィルタリングして「XML」タブに移動し、XPathコードをコピーします。必要に応じてこの行を手動で調整できます。ログリスト全体をCSV形式でエクスポートするには、次のコマンドを使用します。
$events = Get-WinEvent -FilterXML $xmlQuery $events | Export-CSV "C:\Logs\FilteredEvents.csv" -NoTypeInformation -Encoding UTF8
リモートマシンからログを取得する
ネットワーク内の他のマシンのログを取得したいですか?-ComputerNameパラメータを指定して、リモートホスト名を追加するだけです。
$server = 'mun-dc01' Get-WinEvent -ComputerName $server -LogName System -MaxEvents 50 | Select-Object Message, Id, TimeCreated
複数のサーバーの場合は、テキスト ファイルからリストを読み取ることができます。
$servers = Get-Content -Path C:\ps\servers.txt foreach ($srv in $servers) { Get-WinEvent -ComputerName $srv -LogName System -MaxEvents 5 | Select-Object MachineName, Id, Message, TimeCreated }
また、ドメイン全体の検索、特にアカウント ロックアウトなどのセキュリティ イベントの場合は、すべてのドメイン コントローラーをクエリする場合があります。
$Username = 'a.muller' Get-ADDomainController -Filter * | ForEach-Object { $GweParams = @{ 'ComputerName' = $_. Hostname 'LogName' = 'Security' 'FilterXPath' = "*[System[EventID=4740] and EventData[Data[@Name='TargetUserName']='$Username']]" } Get-WinEvent @GweParams }
ちょっとしたスクリプトの魔法で、どれだけ多くの情報を取得できるかは、本当に驚きです。重要なのは、どの属性でフィルタリングするか、そしてクエリを効率的に構築する方法を理解することです。
まとめ
PowerShellのGet-WinEventツールは、ログを頻繁に処理する場合や、複数のソースから迅速かつ詳細な情報を取得する必要がある場合に、ほぼ必須です。組み込みフィルターとカスタムXMLクエリを組み合わせることで、時間を節約し、トラブルシューティングを大幅にスムーズに行うことができます。適切なコマンド、フィルター、あるいはサーバー全体で確認すべき場所を知っているだけで、状況が一変することがあります。確かに、すぐに複雑になってしまうこともありますが、少し練習すれば、自動化の威力を実感できるでしょう。
まとめ
- すべてのログにアクセスするには、PowerShell を管理者として実行します。
Get-WinEvent -LogName...基本的なログ プルに使用します。- FilterHashtableを使用してフィルタリングを高速化します。
- クエリが複雑ですか?生成された XML でFilterXmlを使用してください。
- リモート ログの場合は、-ComputerNameを指定します。
- 複数のフィルターを組み合わせて効率的に検索します。
まとめ
ログ調査やタスクの自動化のスピードアップにお役立ていただければ幸いです。一度コツをつかめば、非常に簡単で、イベントビューアーをクリックするよりもはるかに高速です。ぜひ、作業の効率化と時間の節約に役立ててください!