WindowsServer 2025 総合ガイド 第08回
イベントログとパフォーマンス監視 ― トラブルシューティングの基本
第7回では、Windows Defender Firewallの基本概念と実践的な規則の管理を学びました。第8回となる今回は、サーバー運用において欠かせない「イベントログ」と「パフォーマンス監視」について学びます。サーバーに問題が発生した際に「何が起きたのか」「原因は何か」を調査するスキルは、インフラエンジニアにとって最も重要な能力のひとつです。イベントログの読み方、PowerShellによるログの検索・分析方法、パフォーマンスカウンターを使ったリソース監視の方法を、実践的に習得していきましょう。
8.1 この記事で学ぶこと
- イベントログの構造(ログの種類、イベントレベル、イベントID)を理解する
Get-WinEventコマンドレットを使い、PowerShellでイベントログを検索・フィルタリングできる- ログの分析結果をCSVファイル等にエクスポートできる
Get-Processでプロセスの状態を確認し、リソース消費の多いプロセスを特定できるGet-Counterでパフォーマンスカウンターを取得し、CPU・メモリ・ディスクの使用状況を監視できる- 「サーバーが重い」「エラーが出た」といった問題に対して、論理的な調査手順を実行できる
8.2 前提条件
- 第7回完了(Windows Defender Firewallの設定ができる状態)
- Windows Server 2025にリモートデスクトップ接続できる状態
- PowerShell 7.4を管理者として起動できる状態
8.3 イベントログとは
サーバーが正常に動作しているときは特に意識することのないイベントログですが、障害が発生した際には最初に確認すべき情報源となります。イベントログとは、Windows OSが「いつ、何が起きたか」を時系列で記録する仕組みです。
8.3.1 イベントログの役割
イベントログは、Windows OSが自動的に記録する「システムの活動記録」です。人間が日記をつけるように、OSはシステム上で発生したさまざまな出来事をイベントログに書き込みます。
イベントログが記録する情報には、たとえば以下のようなものがあります。
- サービスの起動・停止: どのサービスが、いつ起動または停止したか
- エラーの発生: アプリケーションやドライバーでどのようなエラーが発生したか
- セキュリティイベント: 誰がいつログオンしたか、ログオンに失敗したか
- システムの変更: 設定変更やアップデートの適用
実務では、「サーバーが突然再起動した」「サービスが動かなくなった」といった問題が発生した際に、イベントログを確認することで原因を特定します。イベントログは、トラブルシューティングの出発点となる最重要情報源です。
8.3.2 主要なログの種類
Windows Serverには多数のイベントログがありますが、まず覚えるべきは以下の4つです。
| ログ名 | 記録される内容 | 確認する場面 |
|---|---|---|
| Application | アプリケーションに関するイベント(.NETランタイムエラー、アプリケーションのクラッシュ等) | アプリケーションが動かない・落ちるとき |
| System | OS・ドライバーに関するイベント(サービスの起動・停止、ハードウェアエラー等) | サーバーが不安定・サービスが停止したとき |
| Security | セキュリティ監査イベント(ログオン成功・失敗、アクセス権の変更等) | 不正アクセスが疑われるとき |
| Setup | Windows Updateや機能の追加・削除に関するイベント | アップデート後に問題が発生したとき |
日常的なトラブルシューティングでは、SystemログとApplicationログを最も頻繁に確認します。セキュリティ監査が必要な場面では、Securityログも重要な確認対象です。
8.3.3 イベントレベル
各イベントには「レベル」が設定されており、そのイベントの重要度を示しています。レベルには対応する数値があり、フィルタリングの際にはこの数値を使用します。
| レベル | 数値 | 意味 | 対応の目安 |
|---|---|---|---|
| Critical(重大) | 1 | システムに深刻な障害が発生した | 即座に対応が必要 |
| Error(エラー) | 2 | 機能に問題が発生したが、システムは稼働中 | 早急に調査が必要 |
| Warning(警告) | 3 | 将来的に問題になる可能性がある | 計画的に対処 |
| Information(情報) | 4 | 正常な動作の記録 | 通常は確認不要 |
ポイント: フィルタリングで使用するレベルの数値は、直感に反して「値が小さいほど重大」です。Critical = 1、Error = 2、Warning = 3、Information = 4 と覚えてください。この数値は、後述する
-FilterHashtableでログを絞り込む際に使用します。
8.3.4 イベントID
イベントID(Event ID)は、各イベントを一意に識別する番号です。たとえば「イベントID 7036」は「サービスの状態が変わった(起動または停止)」ことを示します。
イベントIDを知っておくと、ログの中から特定の種類のイベントを素早く検索できます。以下は、Windows Serverでよく目にする代表的なイベントIDです。
| ログ | イベントID | 意味 |
|---|---|---|
| System | 6005 | イベントログサービスが開始した(= システム起動) |
| System | 6006 | イベントログサービスが停止した(= 正常シャットダウン) |
| System | 6008 | 予期しないシャットダウンが発生した |
| System | 7000 | サービスが起動に失敗した |
| System | 7023 | サービスがエラーで終了した |
| System | 7034 | サービスが予期せず終了した |
| System | 7036 | サービスの状態が変化した(起動/停止) |
| System | 1074 | システムの再起動またはシャットダウンが開始された |
| System | 41 | 予期しない再起動が発生した(Kernel-Power) |
| Application | 1000 | アプリケーションエラー(クラッシュ) |
| Application | 1026 | .NET Runtimeエラー |
| Security | 4624 | ログオン成功 |
| Security | 4625 | ログオン失敗 |
| Security | 4634 | ログオフ |
Tips: イベントIDの意味がわからない場合は、Microsoft Docsで「Event ID + 番号」を検索してください。たとえば「Event ID 7036」で検索すると、そのイベントの詳細な説明と対処法が見つかります。また、イベントビューアー上のイベント詳細画面にある「オンライン ヘルプのリンク」からも公式ドキュメントにアクセスできます。
8.4 イベントログの参照
イベントログの構造を理解したところで、実際にPowerShellを使ってログを参照してみましょう。イベントログの参照にはGet-WinEventコマンドレットを使用します。
8.4.1 Get-WinEventコマンドレット
Get-WinEventは、Windows Server 2025でイベントログを取得するための標準的なコマンドレットです。古いPowerShellではGet-EventLogというコマンドレットも使われていましたが、PowerShell 6以降で非推奨となり、PowerShell 7.4では使用できません。本シリーズではGet-WinEventを使用します。
Get-WinEventの基本構文は以下のとおりです。
[実行環境: PowerShell 7.4 (管理者)]
# 基本構文
Get-WinEvent -LogName 'ログ名' -MaxEvents 取得件数
主要なパラメータは以下のとおりです。
| パラメータ | 説明 | 例 |
|---|---|---|
-LogName |
取得するログの名前を指定 | -LogName 'System' |
-MaxEvents |
取得するイベントの最大件数 | -MaxEvents 10 |
-FilterHashtable |
ハッシュテーブルで条件を指定してフィルタリング | 後述 |
-Oldest |
古いイベントから順に取得(デフォルトは新しい順) | -Oldest |
8.4.2 利用可能なログの確認
まず、サーバーにどのようなイベントログが存在するかを確認してみましょう。
[実行環境: PowerShell 7.4 (管理者)]
# 利用可能なログの一覧を確認(レコードが1件以上あるもの)
Get-WinEvent -ListLog * |
Where-Object -Property RecordCount -GT 0 |
Sort-Object -Property RecordCount -Descending |
Select-Object -Property LogName, RecordCount, MaximumSizeInBytes |
Format-Table -AutoSize
実行結果の例:
LogName RecordCount MaximumSizeInBytes
------- ----------- ------------------
Security 15234 20971520
System 5678 20971520
Application 3421 20971520
Microsoft-Windows-PowerShell/Operational 1205 1052672
Windows PowerShell 893 15728640
Microsoft-Windows-TaskScheduler/Operational 456 1052672
Setup 128 10485760
...
Windows Server 2025には数百種類のイベントログが存在しますが、実務で最も頻繁に確認するのは先述の4つ(System、Application、Security、Setup)です。
8.4.3 基本的なログ取得
直近のシステムログとアプリケーションログを取得してみましょう。
[実行環境: PowerShell 7.4 (管理者)]
# 直近10件のシステムログを取得
Get-WinEvent -LogName 'System' -MaxEvents 10 |
Select-Object -Property TimeCreated, Id, LevelDisplayName, Message |
Format-Table -AutoSize -Wrap
実行結果の例:
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
2026/02/08 14:23:15 7036 Information The Windows Time service entered the running state.
2026/02/08 14:23:10 7036 Information The Windows Time service entered the stopped state.
2026/02/08 14:20:05 16 Information The access history in hive \??\C:\Windows\AppCompat\Programs...
2026/02/08 14:15:32 7040 Information The start type of the Background Intelligent Transfer...
2026/02/08 13:58:21 10 Warning The driver \Device\Harddisk0\DR0 did not respond within the timeout...
...
[実行環境: PowerShell 7.4 (管理者)]
# 直近5件のアプリケーションログを取得
Get-WinEvent -LogName 'Application' -MaxEvents 5 |
Select-Object -Property TimeCreated, Id, LevelDisplayName, ProviderName, Message |
Format-List
実行結果の例:
TimeCreated : 2026/02/08 14:10:22
Id : 1000
LevelDisplayName : Error
ProviderName : Application Error
Message : Faulting application name: example.exe, version: 1.0.0.0...
TimeCreated : 2026/02/08 13:45:18
Id : 1001
LevelDisplayName : Information
ProviderName : Windows Error Reporting
Message : Fault bucket...
...
注意: Securityログを参照するには管理者権限が必要です。一般ユーザーのPowerShellでは「Access is denied」エラーが発生します。管理者としてPowerShellを起動してから実行してください。
8.5 ログのフィルタリング
イベントログには膨大な量のイベントが記録されています。すべてのログを順番に読むのは現実的ではありません。実務では、-FilterHashtableパラメータを使って必要なログだけを効率的に絞り込みます。
8.5.1 -FilterHashtableによるフィルタ
-FilterHashtableは、ハッシュテーブル(キーと値のペア)を使ってフィルタ条件を指定するパラメータです。Where-Objectでパイプライン上でフィルタリングするよりも高速に動作します。これは、-FilterHashtableがWindowsのイベントログエンジンに直接フィルタ条件を渡すため、不要なデータの読み込みを最初からスキップできるためです。
-FilterHashtableで使用できる主なキーは以下のとおりです。
| キー | 説明 | 値の例 |
|---|---|---|
LogName |
ログの名前 | 'System'、'Application' |
Level |
イベントレベル(数値) | 1(Critical)、2(Error)、3(Warning) |
ID |
イベントID | 7036、4624 |
StartTime |
検索開始日時 | (Get-Date).AddHours(-24) |
EndTime |
検索終了日時 | (Get-Date) |
ProviderName |
イベントソース名 | 'Service Control Manager' |
8.5.2 実践的なフィルタ例
ここからは、実務でよく使うフィルタリングパターンを順に紹介します。
直近24時間のエラーのみ抽出
トラブルシューティングで最も基本的な操作です。直近24時間に発生したエラーイベントを抽出します。
[実行環境: PowerShell 7.4 (管理者)]
# 直近24時間のシステムログからエラー(Level 2)を抽出
$startTime = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = $startTime
} | Select-Object -Property TimeCreated, Id, LevelDisplayName, Message |
Format-Table -AutoSize -Wrap
実行結果の例:
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
2026/02/08 10:15:32 7023 Error The Windows Update service terminated with the following error:...
2026/02/08 03:42:18 7000 Error The Application Host Helper Service service failed to start...
2026/02/07 22:30:45 36 Error The time provider NtpClient was unable to find a domain...
ポイント: エラーとCriticalの両方を取得したい場合は、
Level = 1,2のように配列で指定できます。
[実行環境: PowerShell 7.4 (管理者)]
# 直近24時間のCriticalとErrorを両方取得
$startTime = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 1, 2
StartTime = $startTime
} | Select-Object -Property TimeCreated, Id, LevelDisplayName, Message |
Format-Table -AutoSize -Wrap
特定のイベントIDを検索
特定のイベントIDがわかっている場合、そのIDのイベントだけを検索できます。
[実行環境: PowerShell 7.4 (管理者)]
# サービス起動失敗(イベントID 7000)を検索
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ID = 7000
} -MaxEvents 5 |
Select-Object -Property TimeCreated, Id, LevelDisplayName, Message |
Format-List
実行結果の例:
TimeCreated : 2026/02/08 03:42:18
Id : 7000
LevelDisplayName : Error
Message : The Application Host Helper Service service failed to start
due to the following error:
The service did not respond to the start or control request in a timely fashion.
特定のサービスに関するログ
特定のイベントソース(ProviderName)に絞り込んでログを取得できます。サービスの起動・停止に関するイベントは「Service Control Manager」というプロバイダーが記録します。
[実行環境: PowerShell 7.4 (管理者)]
# Service Control Managerのイベントを直近20件取得
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ProviderName = 'Service Control Manager'
} -MaxEvents 20 |
Select-Object -Property TimeCreated, Id, LevelDisplayName, Message |
Format-Table -AutoSize -Wrap
時間範囲を指定して検索
「昨日の深夜2時から4時の間に何が起きたか」といった調査では、StartTimeとEndTimeの両方を指定します。
[実行環境: PowerShell 7.4 (管理者)]
# 特定の時間範囲でシステムログを検索
$startTime = [datetime]"2026/02/07 02:00:00"
$endTime = [datetime]"2026/02/07 04:00:00"
Get-WinEvent -FilterHashtable @{
LogName = 'System'
StartTime = $startTime
EndTime = $endTime
} | Select-Object -Property TimeCreated, Id, LevelDisplayName, Message |
Format-Table -AutoSize -Wrap
よくあるエラーと対処法
| エラー | 原因 | 対処法 |
|---|---|---|
No events were found that match the specified selection criteria. |
指定した条件に合致するイベントがない | 条件を緩くして再検索(時間範囲を広げる、Levelを外す等) |
Access is denied |
管理者権限がない状態でSecurityログ等を参照しようとした | 管理者権限でPowerShellを起動し直す |
There is not an event log on the ... computer that matches |
指定したログ名が存在しない | Get-WinEvent -ListLog *でログ名を確認 |
8.6 ログの分析と出力
必要なログを取得できるようになったら、次は取得したログを分析しやすい形に加工し、ファイルとして保存する方法を学びます。
8.6.1 必要な情報の抽出
イベントログのオブジェクトには多くのプロパティが含まれていますが、実際に必要な情報は限られています。Select-Objectで必要なプロパティだけを抽出しましょう。
[実行環境: PowerShell 7.4 (管理者)]
# イベントログが持つプロパティを確認
Get-WinEvent -LogName 'System' -MaxEvents 1 |
Get-Member -MemberType Property
実行結果の例:
TypeName: System.Diagnostics.Eventing.Reader.EventLogRecord
Name MemberType Definition
---- ---------- ----------
ActivityId Property System.Nullable[guid] ActivityId {get;}
Bookmark Property System.Diagnostics.Eventing.Reader.EventBookmark Bookmark {get;}
ContainerLog Property string ContainerLog {get;}
Id Property int Id {get;}
Keywords Property System.Nullable[long] Keywords {get;}
KeywordsDisplayNames Property System.Collections.Generic.IEnumerable[string] KeywordsDisplay...
Level Property System.Nullable[byte] Level {get;}
LevelDisplayName Property string LevelDisplayName {get;}
LogName Property string LogName {get;}
MachineName Property string MachineName {get;}
Message Property string Message {get;}
...
TimeCreated Property System.Nullable[datetime] TimeCreated {get;}
トラブルシューティングでよく使用するプロパティは以下のとおりです。
| プロパティ | 説明 |
|---|---|
TimeCreated |
イベントが発生した日時 |
Id |
イベントID |
LevelDisplayName |
イベントレベルの表示名(Error、Warning等) |
ProviderName |
イベントソース(どのコンポーネントが記録したか) |
Message |
イベントの詳細メッセージ |
[実行環境: PowerShell 7.4 (管理者)]
# 実務で使いやすい形式でエラーログを取得
$startTime = (Get-Date).AddDays(-7)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 1, 2
StartTime = $startTime
} | Select-Object -Property @(
'TimeCreated'
'Id'
'LevelDisplayName'
'ProviderName'
@{ Name = 'ShortMessage'; Expression = { $_.Message.Split("`n")[0] } }
) | Format-Table -AutoSize -Wrap
上記の例では、カスタムプロパティ(ShortMessage)を定義して、長いメッセージの1行目だけを表示しています。実際のメッセージは複数行にわたることが多いため、一覧表示時はこのように先頭行だけを表示すると見やすくなります。
8.6.2 ログのエクスポート
取得したログを他のメンバーと共有したり、後から分析したりするために、ファイルに保存する方法を紹介します。
CSVファイルへの出力
CSVファイルはExcelで開くことができるため、チームでの共有や報告書作成に便利です。
[実行環境: PowerShell 7.4 (管理者)]
# 直近7日間のエラーログをCSVファイルに出力
$startTime = (Get-Date).AddDays(-7)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 1, 2, 3
StartTime = $startTime
} | Select-Object -Property TimeCreated, Id, LevelDisplayName, ProviderName, Message |
Export-Csv -Path "C:\Logs\SystemErrors_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation -Encoding UTF8
Write-Host "ログをエクスポートしました: C:\Logs\SystemErrors_$(Get-Date -Format 'yyyyMMdd').csv" -ForegroundColor Green
注意: 出力先のフォルダ(
C:\Logs)が存在しない場合はエラーになります。事前にNew-Item -Path "C:\Logs" -ItemType Directory -Forceでフォルダを作成しておいてください。
テキストファイルへの出力
テキストファイルへの出力も簡単です。メモ帳などで手軽に確認できます。
[実行環境: PowerShell 7.4 (管理者)]
# 直近24時間のエラーログをテキストファイルに出力
$startTime = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = $startTime
} | Format-List -Property TimeCreated, Id, LevelDisplayName, ProviderName, Message |
Out-File -FilePath "C:\Logs\SystemErrors_Detail.txt" -Encoding UTF8
Write-Host "ログをエクスポートしました: C:\Logs\SystemErrors_Detail.txt" -ForegroundColor Green
8.7 パフォーマンス監視の基礎
イベントログが「過去に何が起きたか」を記録するものであるのに対し、パフォーマンス監視は「今、サーバーがどのような状態にあるか」をリアルタイムで確認するための手段です。
8.7.1 なぜパフォーマンス監視が必要か
実務で最もよくある問い合わせのひとつが「サーバーが重い」です。しかし「重い」だけでは原因がわかりません。原因を特定するためには、サーバーのリソースがどの程度使われているかをデータで確認する必要があります。
パフォーマンス監視は、主に2つの目的で使用されます。
- 障害時の原因特定: 「何がリソースを消費しているのか」を特定する
- 予兆の検知: リソースの使用率がじわじわ上昇していることを発見し、障害が起きる前に対処する
8.7.2 監視対象のリソース
サーバーパフォーマンスの監視で注目すべきリソースは、大きく4つあります。
| リソース | 指標 | 注意が必要な状態 |
|---|---|---|
| CPU | プロセッサ使用率 | 常時80%以上が続く |
| メモリ | 物理メモリの使用量・空き容量 | 空きメモリが数百MB以下 |
| ディスクI/O | ディスクの使用率・キュー長 | ディスクキュー長が常時2以上 |
| ネットワーク | 帯域使用量 | 帯域上限に近づいている |
これらのリソースを確認する方法を、プロセス監視とパフォーマンスカウンターの2つのアプローチで学んでいきます。
8.8 プロセス監視
パフォーマンスの問題を調査する際、まず確認すべきは「どのプロセスがリソースを消費しているか」です。Get-Processコマンドレットを使って、実行中のプロセスの状態を確認します。
8.8.1 Get-Processコマンドレット
Get-Processは、現在実行中のすべてのプロセス情報を取得するコマンドレットです。
[実行環境: PowerShell 7.4 (管理者)]
# 実行中プロセスの一覧を取得
Get-Process |
Select-Object -Property Id, ProcessName, CPU,
@{ Name = 'MemoryMB'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } } |
Sort-Object -Property CPU -Descending |
Select-Object -First 15 |
Format-Table -AutoSize
実行結果の例:
Id ProcessName CPU MemoryMB
-- ----------- --- --------
1284 svchost 312.45 145.3
804 MsMpEng 198.72 210.5
2156 pwsh 85.34 98.2
456 csrss 42.18 12.8
1632 WmiPrvSE 38.90 45.6
512 lsass 25.63 32.1
68 services 18.45 18.9
924 rdpclip 12.30 8.4
...
ここで表示されるCPUプロパティは「プロセスが起動してからのCPU使用時間の合計(秒)」です。CPU使用率(%)ではないことに注意してください。長く動いているプロセスほど値が大きくなるため、値が大きいからといって「今」CPUを大量に使っているとは限りません。
8.8.2 CPU使用率の高いプロセスの特定
「今」CPUを大量に消費しているプロセスを特定するには、2つの時点のCPU時間を比較する方法が有効です。
[実行環境: PowerShell 7.4 (管理者)]
# 5秒間隔で2回計測し、CPU使用量の差分からCPU使用率を推定
$sample1 = Get-Process | Select-Object -Property Id, ProcessName, CPU
Start-Sleep -Seconds 5
$sample2 = Get-Process | Select-Object -Property Id, ProcessName, CPU
# 差分を計算して表示
$sample2 | ForEach-Object -Process {
$proc = $_
$prev = $sample1 | Where-Object -Property Id -EQ $proc.Id
if ($prev -and $proc.CPU -and $prev.CPU) {
[PSCustomObject]@{
Id = $proc.Id
ProcessName = $proc.ProcessName
CPUDiff = [math]::Round($proc.CPU - $prev.CPU, 2)
}
}
} | Where-Object -Property CPUDiff -GT 0 |
Sort-Object -Property CPUDiff -Descending |
Select-Object -First 10 |
Format-Table -AutoSize
実行結果の例:
Id ProcessName CPUDiff
-- ----------- -------
804 MsMpEng 2.34
1284 svchost 0.89
2156 pwsh 0.45
456 csrss 0.12
この結果から、計測期間中にCPUを最も多く使用していたプロセスを特定できます。上記の例では、MsMpEng(Windows Defenderのマルウェア対策サービス)が最もCPUを消費しています。
8.8.3 メモリ消費量の確認
メモリの消費量は、Get-Processが返すプロパティから直接確認できます。
[実行環境: PowerShell 7.4 (管理者)]
# メモリ使用量の多いプロセス上位10件を表示
Get-Process |
Sort-Object -Property WorkingSet64 -Descending |
Select-Object -First 10 -Property Id, ProcessName,
@{ Name = 'WorkingSetMB'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } },
@{ Name = 'VirtualMemoryMB'; Expression = { [math]::Round($_.VirtualMemorySize64 / 1MB, 1) } } |
Format-Table -AutoSize
実行結果の例:
Id ProcessName WorkingSetMB VirtualMemoryMB
-- ----------- ------------ ---------------
804 MsMpEng 210.5 2048.3
1284 svchost 145.3 1024.7
2156 pwsh 98.2 512.8
512 lsass 32.1 256.4
1632 WmiPrvSE 45.6 384.2
...
WorkingSet64(WorkingSet)は、プロセスが現在使用している物理メモリの量です。VirtualMemorySize64は仮想メモリの使用量で、物理メモリだけでなくディスク上のページファイルも含みます。通常のトラブルシューティングでは、WorkingSet(物理メモリ使用量)を確認します。
8.8.4 プロセスの強制終了
応答しなくなったプロセスや、異常にリソースを消費しているプロセスは、Stop-Processコマンドレットで強制終了できます。
⚠ 警告:
Stop-Processはプロセスを即座に強制終了します。プロセスが処理中のデータは保存されずに失われます。データベースサーバーやファイルサーバーのプロセスを強制終了すると、データの破損や損失が発生する可能性があります。本番環境では、まず正規の停止手順(サービスの停止等)を試し、それでも停止しない場合の最終手段として使用してください。
[実行環境: PowerShell 7.4 (管理者)]
# プロセスIDを指定して強制終了
Stop-Process -Id 2156 -Force
# プロセス名を指定して強制終了(同名プロセスがすべて終了される)
Stop-Process -Name "notepad" -Force
| パラメータ | 説明 |
|---|---|
-Id |
プロセスIDを指定して特定のプロセスを終了 |
-Name |
プロセス名を指定して終了(同名プロセスがすべて対象) |
-Force |
確認プロンプトなしで強制終了 |
[実行環境: PowerShell 7.4 (管理者)]
# 安全に確認してから終了する場合は -Confirm を使用
Stop-Process -Id 2156 -Confirm
実行結果の例:
Confirm
Are you sure you want to perform this action?
Performing the operation "Stop-Process" on target "pwsh (2156)".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
8.9 パフォーマンスカウンター
プロセス単位の監視に加えて、システム全体のリソース状況を把握するために「パフォーマンスカウンター」を使用します。パフォーマンスカウンターは、WindowsのOSカーネルが収集しているシステム統計情報であり、CPU使用率やメモリ使用量などの値をリアルタイムで取得できます。
8.9.1 Get-Counterコマンドレット
Get-Counterは、パフォーマンスカウンターの値を取得するコマンドレットです。PowerShell 7.4で使用可能ですが、Windows環境でのみ動作します。
[実行環境: PowerShell 7.4 (管理者)]
# パラメータなしで実行すると、デフォルトのカウンターセットが取得される
Get-Counter
実行結果の例:
Timestamp CounterSamples
--------- --------------
2026/02/08 14:30:15 \\ws2025\network interface(microsoft hyper-v network adapter)\bytes total/sec :
1245.67
\\ws2025\processor(_total)\% processor time :
12.3456
\\ws2025\memory\% committed bytes in use :
45.6789
\\ws2025\memory\cache faults/sec :
23.45
\\ws2025\physicaldisk(_total)\% disk time :
5.678
\\ws2025\physicaldisk(_total)\current disk queue length :
0
8.9.2 主要なカウンター
実務で頻繁に使用する主要なパフォーマンスカウンターを紹介します。カウンターは「\カウンターセット(インスタンス)\カウンター名」という形式で指定します。
| カテゴリ | カウンターパス | 説明 | 注意すべき値 |
|---|---|---|---|
| CPU | \Processor(_Total)\% Processor Time |
CPU全体の使用率(%) | 常時80%以上 |
| メモリ | \Memory\% Committed Bytes In Use |
コミット済みメモリの使用率(%) | 常時90%以上 |
| メモリ | \Memory\Available MBytes |
利用可能な物理メモリ(MB) | 数百MB以下 |
| ディスク | \PhysicalDisk(_Total)\% Disk Time |
ディスクの使用率(%) | 常時80%以上 |
| ディスク | \PhysicalDisk(_Total)\Current Disk Queue Length |
ディスクキュー長 | 常時2以上 |
個々のカウンターを取得してみましょう。
[実行環境: PowerShell 7.4 (管理者)]
# CPU使用率を取得
Get-Counter -Counter '\Processor(_Total)\% Processor Time'
実行結果の例:
Timestamp CounterSamples
--------- --------------
2026/02/08 14:35:22 \\ws2025\processor(_total)\% processor time :
15.2345
[実行環境: PowerShell 7.4 (管理者)]
# 複数のカウンターを一度に取得
Get-Counter -Counter @(
'\Processor(_Total)\% Processor Time'
'\Memory\Available MBytes'
'\Memory\% Committed Bytes In Use'
'\PhysicalDisk(_Total)\% Disk Time'
'\PhysicalDisk(_Total)\Current Disk Queue Length'
)
実行結果の例:
Timestamp CounterSamples
--------- --------------
2026/02/08 14:36:05 \\ws2025\processor(_total)\% processor time :
8.45123
\\ws2025\memory\available mbytes :
823
\\ws2025\memory\% committed bytes in use :
52.345
\\ws2025\physicaldisk(_total)\% disk time :
3.21
\\ws2025\physicaldisk(_total)\current disk queue length :
0
注意: パフォーマンスカウンター名はOSの言語設定によって異なります。日本語版Windows Serverでは
\プロセッサ(_Total)\% プロセッサ時間のようにカウンター名が日本語になっている場合があります。英語版と日本語版でカウンターパスが異なる場合は、Get-Counter -ListSet *でお使いの環境でのカウンター名を確認してください。
8.9.3 継続的な監視
一度の計測だけでは判断できない場合、一定間隔で継続的にカウンターを取得できます。
[実行環境: PowerShell 7.4 (管理者)]
# 5秒間隔で5回サンプリング
Get-Counter -Counter '\Processor(_Total)\% Processor Time' -SampleInterval 5 -MaxSamples 5
実行結果の例:
Timestamp CounterSamples
--------- --------------
2026/02/08 14:40:00 \\ws2025\processor(_total)\% processor time :
12.34
2026/02/08 14:40:05 \\ws2025\processor(_total)\% processor time :
8.56
2026/02/08 14:40:10 \\ws2025\processor(_total)\% processor time :
45.78
2026/02/08 14:40:15 \\ws2025\processor(_total)\% processor time :
22.13
2026/02/08 14:40:20 \\ws2025\processor(_total)\% processor time :
9.87
[実行環境: PowerShell 7.4 (管理者)]
# 継続的な監視(Ctrl+C で停止するまで続ける)
Get-Counter -Counter '\Processor(_Total)\% Processor Time' -SampleInterval 2 -Continuous
| パラメータ | 説明 |
|---|---|
-SampleInterval |
サンプリング間隔(秒)。デフォルトは1秒 |
-MaxSamples |
取得するサンプル数。デフォルトは1 |
-Continuous |
Ctrl+Cで停止するまで連続して取得 |
8.9.4 カウンター一覧の確認
利用可能なカウンターの一覧は-ListSetパラメータで確認できます。
[実行環境: PowerShell 7.4 (管理者)]
# 利用可能なカウンターセットの一覧
Get-Counter -ListSet * |
Select-Object -Property CounterSetName |
Sort-Object -Property CounterSetName
[実行環境: PowerShell 7.4 (管理者)]
# 特定のカウンターセット(例: Memory)に含まれるカウンターを確認
(Get-Counter -ListSet 'Memory').Paths
実行結果の例:
\Memory\Page Faults/sec
\Memory\Available Bytes
\Memory\Committed Bytes
\Memory\Commit Limit
\Memory\Write Copies/sec
\Memory\Transition Faults/sec
\Memory\Cache Faults/sec
\Memory\Demand Zero Faults/sec
\Memory\Pages/sec
\Memory\Pages Input/sec
\Memory\Page Reads/sec
\Memory\Pages Output/sec
\Memory\Pool Paged Bytes
\Memory\Pool Nonpaged Bytes
\Memory\Pool Paged Allocs
\Memory\Pool Nonpaged Allocs
\Memory\Free System Page Table Entries
\Memory\Cache Bytes
\Memory\Cache Bytes Peak
\Memory\Available MBytes
\Memory\% Committed Bytes In Use
...
8.9.5 実用的な監視スクリプト
主要なパフォーマンスカウンターをまとめて取得し、見やすく整形するスクリプトの例を紹介します。
[実行環境: PowerShell 7.4 (管理者)]
# サーバーの主要リソースをまとめて確認
$counters = @(
'\Processor(_Total)\% Processor Time'
'\Memory\Available MBytes'
'\Memory\% Committed Bytes In Use'
'\PhysicalDisk(_Total)\% Disk Time'
'\PhysicalDisk(_Total)\Current Disk Queue Length'
)
$result = Get-Counter -Counter $counters
# 見やすく整形して表示
$result.CounterSamples | ForEach-Object -Process {
[PSCustomObject]@{
Counter = $_.Path.Split('\', 4)[-1]
Value = [math]::Round($_.CookedValue, 2)
}
} | Format-Table -AutoSize
実行結果の例:
Counter Value
------- -----
processor(_total)\% processor time 12.34
memory\available mbytes 823
memory\% committed bytes in use 52.35
physicaldisk(_total)\% disk time 3.21
physicaldisk(_total)\current disk queue length 0
8.10 トラブルシューティングのフローチャート
ここまで学んだイベントログとパフォーマンス監視のスキルを組み合わせて、実務で頻発する「サーバーが重い」という問題を調査するフローチャートを紹介します。論理的な手順に従って調査を進めることで、効率的に原因を特定できます。
8.10.1 「サーバーが重い」と言われたときの調査手順
以下の手順に沿って、順番にリソースを確認していきます。
Step 1:現象の確認(何が遅いのか)
まず「重い」の具体的な内容を確認します。「Webサイトの表示が遅い」「RDPの操作がカクつく」「ファイルのコピーが遅い」など、現象によって原因の見当がつきます。
Step 2:CPU使用率の確認
[実行環境: PowerShell 7.4 (管理者)]
# CPU使用率を確認(5秒間隔で3回)
Get-Counter -Counter '\Processor(_Total)\% Processor Time' -SampleInterval 5 -MaxSamples 3
CPU使用率が常時80%を超えている場合 → Step 5(原因プロセスの特定)へ
Step 3:メモリ使用量の確認
[実行環境: PowerShell 7.4 (管理者)]
# 利用可能メモリとコミット率を確認
Get-Counter -Counter @(
'\Memory\Available MBytes'
'\Memory\% Committed Bytes In Use'
)
利用可能メモリが数百MB以下、またはコミット率が90%以上の場合 → Step 5へ
Step 4:ディスクI/Oの確認
[実行環境: PowerShell 7.4 (管理者)]
# ディスク使用率とキュー長を確認
Get-Counter -Counter @(
'\PhysicalDisk(_Total)\% Disk Time'
'\PhysicalDisk(_Total)\Current Disk Queue Length'
) -SampleInterval 5 -MaxSamples 3
ディスク使用率が常時80%以上、またはキュー長が常時2以上の場合 → Step 5へ
Step 5:原因プロセスの特定
[実行環境: PowerShell 7.4 (管理者)]
# CPU消費量の多いプロセスを特定
Get-Process |
Sort-Object -Property CPU -Descending |
Select-Object -First 10 -Property Id, ProcessName, CPU,
@{ Name = 'MemoryMB'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } } |
Format-Table -AutoSize
Step 6:対処
原因プロセスが特定できたら、以下のいずれかの対処を行います。
- プロセスの再起動: 該当サービスを再起動する(
Restart-Service) - プロセスの強制終了: 応答しない場合は
Stop-Processで強制終了(データ損失のリスクあり) - リソースの増強: CPUやメモリの割り当てを増やす(VPSのプラン変更等)
- 根本原因の調査: イベントログでエラーの原因を調査する
8.10.2 CPU高負荷時の原因特定
CPU使用率が高い場合の具体的な調査手順です。
[実行環境: PowerShell 7.4 (管理者)]
# Step 1: 現在のCPU使用率を確認
Get-Counter -Counter '\Processor(_Total)\% Processor Time' -SampleInterval 2 -MaxSamples 5 |
ForEach-Object -Process {
$_.CounterSamples | ForEach-Object -Process {
Write-Host ("[{0}] CPU使用率: {1:F1}%" -f (Get-Date -Format 'HH:mm:ss'), $_.CookedValue)
}
}
# Step 2: CPUを消費しているプロセスを特定
Write-Host "`n--- CPU消費量の多いプロセス ---" -ForegroundColor Yellow
Get-Process |
Where-Object -Property CPU -GT 0 |
Sort-Object -Property CPU -Descending |
Select-Object -First 5 -Property Id, ProcessName, CPU,
@{ Name = 'MemoryMB'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } } |
Format-Table -AutoSize
# Step 3: 該当プロセスに関連するイベントログを確認
Write-Host "--- 直近1時間のシステムエラー ---" -ForegroundColor Yellow
$startTime = (Get-Date).AddHours(-1)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 1, 2
StartTime = $startTime
} -ErrorAction SilentlyContinue |
Select-Object -Property TimeCreated, Id, ProviderName,
@{ Name = 'ShortMessage'; Expression = { $_.Message.Split("`n")[0] } } |
Format-Table -AutoSize -Wrap
8.10.3 メモリ不足時の対処法
メモリの空き容量が少ない場合は、以下の手順で調査と対処を行います。
[実行環境: PowerShell 7.4 (管理者)]
# メモリの状態を確認
$memCounter = Get-Counter -Counter @(
'\Memory\Available MBytes'
'\Memory\% Committed Bytes In Use'
)
$memCounter.CounterSamples | ForEach-Object -Process {
Write-Host ("{0}: {1:F1}" -f $_.Path.Split('\')[-1], $_.CookedValue)
}
# メモリ消費量の多いプロセス上位10件
Write-Host "`n--- メモリ消費量の多いプロセス ---" -ForegroundColor Yellow
Get-Process |
Sort-Object -Property WorkingSet64 -Descending |
Select-Object -First 10 -Property Id, ProcessName,
@{ Name = 'WorkingSetMB'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } } |
Format-Table -AutoSize
メモリ不足時の対処の優先順位は以下のとおりです。
- 不要なプロセスを停止する(使っていないアプリケーション等)
- メモリリークが疑われるプロセスを再起動する(メモリ使用量が異常に大きいプロセス)
- メモリの増設やVPSプランの変更を検討する
8.10.4 ディスクI/Oボトルネックの確認
ディスクI/Oが遅い場合は、ディスクの使用率とキュー長を確認します。
[実行環境: PowerShell 7.4 (管理者)]
# ディスク関連のカウンターを詳細に確認
Get-Counter -Counter @(
'\PhysicalDisk(_Total)\% Disk Time'
'\PhysicalDisk(_Total)\Current Disk Queue Length'
'\PhysicalDisk(_Total)\Disk Reads/sec'
'\PhysicalDisk(_Total)\Disk Writes/sec'
'\PhysicalDisk(_Total)\Avg. Disk sec/Read'
'\PhysicalDisk(_Total)\Avg. Disk sec/Write'
) | ForEach-Object -Process {
$_.CounterSamples | ForEach-Object -Process {
[PSCustomObject]@{
Counter = $_.Path.Split('\')[-1]
Value = [math]::Round($_.CookedValue, 4)
}
}
} | Format-Table -AutoSize
実行結果の例:
Counter Value
------- -----
% Disk Time 3.2100
Current Disk Queue Length 0.0000
Disk Reads/sec 12.3400
Disk Writes/sec 8.5600
Avg. Disk sec/Read 0.0045
Avg. Disk sec/Write 0.0062
ディスクI/Oに問題がある場合のチェックポイントは以下のとおりです。
- ディスクキュー長が常時2以上: ディスクの処理能力が追いついていない状態
- Avg. Disk sec/Read または Write が 0.020秒(20ms)以上: ディスクの応答が遅い
- ディスク使用率が常時80%以上: ディスクが常に忙しい状態
ディスクI/Oのボトルネック対処法としては、ディスクに大量のI/Oを発生させているプロセスの特定と見直し、ディスクの空き容量確認(Get-Volume)、SSDへの換装やより高速なストレージプランへの変更があります。
8.11 よくあるエラーパターンと対処法
実際のサーバー運用で遭遇しやすいエラーパターンと、イベントログを使った調査・対処法を紹介します。
8.11.1 サービス起動失敗
サービスが起動しない場合、Systemログに以下のイベントIDが記録されます。
| イベントID | 意味 | 主な原因 |
|---|---|---|
| 7000 | サービスが起動に失敗した | 実行ファイルが見つからない、権限不足、依存サービスが起動していない |
| 7011 | サービスがタイムアウトした | サービスの起動に30秒以上かかった |
| 7023 | サービスがエラーで終了した | サービス内部でエラーが発生した |
| 7034 | サービスが予期せず終了した | サービスがクラッシュした |
[実行環境: PowerShell 7.4 (管理者)]
# サービス起動失敗のイベントを検索
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ID = 7000, 7011, 7023, 7034
} -MaxEvents 10 |
Select-Object -Property TimeCreated, Id,
@{ Name = 'ShortMessage'; Expression = { $_.Message.Split("`n")[0] } } |
Format-Table -AutoSize -Wrap
対処の手順は以下のとおりです。
- イベントログのMessageからどのサービスが失敗したかを確認
Get-Service -Name 'サービス名'で現在の状態を確認- 依存サービスの状態を確認(
Get-Service -Name 'サービス名' | Select-Object -Property DependentServices, ServicesDependedOn) - 依存サービスが停止していれば先に起動
Start-Serviceでサービスの起動を試行
8.11.2 ディスク容量不足
ディスクの空き容量が不足すると、さまざまなサービスが正常に動作しなくなります。
[実行環境: PowerShell 7.4 (管理者)]
# ディスクの空き容量を確認
Get-Volume |
Where-Object -Property DriveLetter |
Select-Object -Property DriveLetter, FileSystemLabel,
@{ Name = 'SizeGB'; Expression = { [math]::Round($_.Size / 1GB, 1) } },
@{ Name = 'FreeSpaceGB'; Expression = { [math]::Round($_.SizeRemaining / 1GB, 1) } },
@{ Name = 'UsedPercent'; Expression = {
[math]::Round(($_.Size - $_.SizeRemaining) / $_.Size * 100, 1)
} } |
Format-Table -AutoSize
実行結果の例:
DriveLetter FileSystemLabel SizeGB FreeSpaceGB UsedPercent
----------- --------------- ------ ----------- -----------
C 99.5 42.3 57.5
ディスク容量が不足した場合の対処法は以下のとおりです。
- 一時ファイルの削除:
Remove-Item -Path "$env:TEMP\*" -Recurse -Force -ErrorAction SilentlyContinue - Windows Updateのキャッシュ削除:
C:\Windows\SoftwareDistribution\Download内のファイルを削除(サービス停止後) - ログファイルの確認とアーカイブ
- ディスクの拡張(VPSのストレージプラン変更等)
8.11.3 認証エラー
不正なログオン試行やパスワード間違いは、SecurityログにイベントID 4625として記録されます。
[実行環境: PowerShell 7.4 (管理者)]
# ログオン失敗イベントを検索
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4625
} -MaxEvents 10 |
Select-Object -Property TimeCreated,
@{ Name = 'Account'; Expression = { $_.Properties[5].Value } },
@{ Name = 'SourceIP'; Expression = { $_.Properties[19].Value } },
@{ Name = 'FailureReason'; Expression = { $_.Properties[8].Value } } |
Format-Table -AutoSize
実行結果の例:
TimeCreated Account SourceIP FailureReason
----------- ------- -------- -------------
2026/02/08 13:45:22 Administrator 198.51.100.45 %%2313
2026/02/08 12:30:18 admin 203.0.113.78 %%2313
2026/02/08 11:15:05 root 198.51.100.123 %%2313
見知らぬIPアドレスから繰り返しログオン失敗が記録されている場合は、不正アクセスの試行(ブルートフォース攻撃)の可能性があります。第7回で学んだファイアウォールの設定で、該当IPアドレスからの接続をブロックすることを検討してください。
8.11.4 ネットワーク関連エラー
ネットワーク関連のエラーは、Systemログのさまざまなプロバイダーによって記録されます。
[実行環境: PowerShell 7.4 (管理者)]
# ネットワーク関連のエラーを検索
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 2, 3
StartTime = (Get-Date).AddDays(-1)
} | Where-Object -FilterScript {
$_.ProviderName -match 'Tcpip|DNS|DHCP|NetBT|NetworkProfile'
} | Select-Object -Property TimeCreated, Id, ProviderName,
@{ Name = 'ShortMessage'; Expression = { $_.Message.Split("`n")[0] } } |
Format-Table -AutoSize -Wrap
ネットワーク関連の問題は、第6回で学んだTest-ConnectionやTest-NetConnectionと組み合わせて調査します。イベントログで「いつから問題が起きているか」を確認し、ネットワークコマンドで「現在の状態」を確認するという2段階のアプローチが効果的です。
8.12 まとめ
今回は、イベントログとパフォーマンス監視について学びました。
- イベントログの基礎
- イベントログはシステムの活動記録であり、トラブルシューティングの最重要情報源
- 主要なログはSystem、Application、Security、Setupの4種類
- イベントレベルはCritical(1)、Error(2)、Warning(3)、Information(4)の4段階
- イベントIDで特定の種類のイベントを識別できる
- ログの参照とフィルタリング
Get-WinEventがPowerShell 7.4でのイベントログ取得の標準コマンドレット-FilterHashtableによる効率的なフィルタリング(LogName、Level、ID、StartTime/EndTime、ProviderName)Export-CsvやOut-Fileでログをファイルに保存して共有・分析
- プロセス監視
Get-ProcessでプロセスのCPU時間とメモリ使用量を確認- 2回の計測の差分でリアルタイムのCPU消費プロセスを特定
Stop-Processによる強制終了はデータ損失のリスクがあるため最終手段とする
- パフォーマンスカウンター
Get-CounterでCPU使用率、メモリ、ディスクI/Oのリアルタイム値を取得-SampleIntervalと-MaxSamples(または-Continuous)で継続的な監視が可能- カウンターパスはOS言語によって異なる場合がある
- トラブルシューティング
- 「サーバーが重い」の調査は、CPU → メモリ → ディスクの順にリソースを確認
- 原因プロセスを特定し、再起動・強制終了・リソース増強のいずれかで対処
- イベントログとパフォーマンスカウンターを組み合わせることで、効率的な原因究明が可能
トラブルシューティングの基本は「推測ではなくデータで判断する」ことです。イベントログで「何が起きたか」を確認し、パフォーマンスカウンターで「今の状態」を数値で把握する。この2つのアプローチを使いこなすことで、サーバーの問題に論理的に対処できるようになります。
8.13 次回予告
第9回では「リモート管理の設定 ― OpenSSHとWinRM」と題して、リモート管理の方式(RDP/SSH/WinRM)の違い、OpenSSH Serverの設定方法、PowerShellリモーティング(WinRM)の設定方法を学びます。実務では複数のサーバーをリモートから効率的に管理するスキルが求められます。次回は、その基盤となるリモート接続の設定を習得していきましょう。
