【イベントID 7031】Windowsサービス異常終了の原因分析と自動回復設定
※本記事には広告を含みます。
はじめに
夜間や休日に監視システムから「Windowsサービス停止」のアラートが飛び、システムイベントログを開くとソース Service Control Manager の イベントID 7031(「○○ サービスは予期せぬ原因により終了しました」) が記録されていて、なぜ急に落ちたのか分からず途方に暮れたことはないでしょうか。
私も過去に、社内基幹システムの連携サービスが深夜に突然クラッシュしてイベントID 7031を出し、翌朝までバッチが止まって業務影響を出してしまった苦い経験があります。その後、Applicationログとの相関分析とサービスの「回復(自動再起動)」設定を標準化したことで、深夜の緊急呼び出しをゼロにできました。
イベントID 7031自体は「サービスが異常終了した事実(結果)」を知らせるログであり、クラッシュの直接原因を突き止めるには別のイベントログとの突き合わせが不可欠です。
この記事では、イベントID 7031が発生した際の原因切り分けフローと、万が一サービスが落ちてもOS側で自動復旧させる「回復(Recovery)」オプションの設計・一括設定手順を解説します。
読み終えるころには、障害発生時の初動調査が5分で完了し、夜間停止を防ぐ堅牢なサービス運用ができるようになります。
この記事の要点
- システムログの「イベントID 7031」はサービス異常終了の検知ログであり、真の原因(例外コードやモジュール名)は同時刻の Applicationログ(イベントID 1000 / 1001 / 1026) に記録されている
- 7031は「回復アクション(自動再起動など)が設定されているサービス」が落ちたときに出力され、回復未設定のサービスが落ちた場合は「7034」が出力される
- サービスの「回復」タブ(または
sc.exe failure)を設定する際は、無限再起動ループを防ぐため「エラーカウントのリセット期間」と「段階的な待機時間」を必ず組み合わせる
| 項目 | 動作確認・検証環境 |
|---|---|
| 検証年月 | 2026年9月 |
| 対象OS | Windows Server 2022 / Windows 11 Pro 24H2 |
| 確認ログ | イベントビューアー(System / Application) |
| 必要権限 | ローカル管理者権限(Administrators) |
結論:イベントID 7031の意味と「7034」との決定的な違い
結論からお伝えすると、Service Control Manager(SCM)が記録する イベントID 7031は「サービスプロセスが正常な停止手順を踏まずに突然クラッシュ(異常終了)し、かつ自動回復アクションがスケジュールされたこと」を示すエラーログ です。
まずは、混同しやすい関連イベントIDとの違いを以下の表で整理します。
| イベントID | ログのソース | メッセージ概要 | 出力される条件・違い |
|---|---|---|---|
| 7031 | Service Control Manager | <サービス名> サービスは予期せぬ原因により終了しました。このサービスの終了は <回数> 回目です。次の修正動作が <ミリ秒> ミリ秒後に実行されます: <アクション> |
サービスが異常終了し、「回復」設定(再起動など)が定義されている場合 に出力される |
| 7034 | Service Control Manager | <サービス名> サービスは予期せぬ原因により終了しました。このサービスの終了は <回数> 回目です。 |
サービスが異常終了し、「回復」設定が「何もしない(未設定)」の場合 に出力される |
| 7023 | Service Control Manager | <サービス名> サービスは次のエラーで終了しました: <エラーコード> |
サービス自身が終了時にWin32エラーコードをSCMへ返して停止した場合に出力される |
| 7036 | Service Control Manager | <サービス名> サービスは 停止(または 実行中) 状態に入りました。 |
正常なサービス起動・停止のステータス変更通知(情報ログ) |
このように、イベントID 7031が出ている時点で、そのサービスには何らかの「回復アクション」が設定されています。しかし、なぜプロセスがクラッシュしたのか(メモリ違反なのか、未処理の例外なのか、DB接続切れなのか)は、7031のメッセージ本文だけでは絶対に分かりません。
真の原因を5分で突き止める!イベントログ相関分析の手順
イベントID 7031を見つけたら、「システム(System)」ログを見るのを一度やめ、同じタイムスタンプ(前後数秒以内)の「アプリケーション(Application)」ログ を確認するのが鉄則です。
1. Applicationログで探すべき3つの重要イベントID
プロセスがクラッシュした際、Windowsのエラー報告機構(WER)やランタイム(.NETなど)は、Applicationログに以下のイベントIDで詳細な検死結果を残します。
- イベントID 1000(ソース:
Application Error): - ネイティブアプリや実行ファイル(
.exe)がクラッシュした際の最重要ログです。「障害が発生しているアプリケーション名」「障害モジュール名(.dll)」「例外コード(例:0xc0000005=アクセス違反 / メモリ参照エラー、0xc0000409=スタックバッファオーバーラン)」が明記されます。 - イベントID 1026(ソース:
.NET Runtime): - .NET製のWindowsサービスが未処理の例外(Unhandled Exception)で落ちた場合、1000の直前にこの1026が出力されます。ソースコードのどの関数(スタックトレース)でどんな例外(
System.OutOfMemoryExceptionやSqlExceptionなど)が起きたかがテキストで丸ごと記録されます。 - イベントID 1001(ソース:
Windows Error Reporting): - クラッシュダンプ(
.dmp)が保存されたパス(C:\ProgramData\Microsoft\Windows\WER\ReportArchive等)が記録されます。
2. PowerShellで7031とApplicationログを時系列で一括抽出する
イベントビューアーのGUIでSystemログとApplicationログを行ったり来たりするのは手間がかかります。以下のPowerShellスクリプトを実行すれば、直近7日間の「7031/7034(System)」と「1000/1026(Application)」をマージし、発生時刻順に並べて一発で原因を突き止められます。
# 直近7日間のサービス異常終了(7031/7034)とアプリクラッシュ(1000/1026)を時系列で統合抽出する
$startTime = (Get-Date).AddDays(-7)
$sysEvents = Get-WinEvent -FilterHashtable @{
LogName = 'System'
ProviderName = 'Service Control Manager'
Id = @(7031, 7034)
StartTime = $startTime
} -ErrorAction SilentlyContinue
$appEvents = Get-WinEvent -FilterHashtable @{
LogName = 'Application'
Id = @(1000, 1026)
StartTime = $startTime
} -ErrorAction SilentlyContinue
# 2つのログを結合して時刻順にソート表示
($sysEvents + $appEvents) |
Sort-Object TimeCreated -Descending |
Select-Object TimeCreated, LogName, Id, ProviderName, @{
Name = "Summary"
Expression = { ($_.Message -split "`r`n")[0..2] -join " / " }
} | Format-Table -AutoSize -Wrap
この出力を見れば、「02:15:03に .NET Runtime (ID 1026) でタイムアウト例外が発生し、同秒に Application Error (ID 1000) でプロセスが落ち、直後に Service Control Manager (ID 7031) が記録された」という因果関係が一目で把握できます。
サービスの「回復(自動再起動)」を安全に設計・コマンド設定する方法
ミドルウェアや監視エージェントなど、一時的な負荷やネットワーク瞬断でまれに落ちることがあるサービスには、サービスの「回復(Recovery)」機能による自動再起動を設定しておくのがベストプラクティスです。
1. GUI(services.msc)での推奨設定値
services.msc を開き、対象サービスのプロパティ > 「回復」タブ で以下のように設定します。
| 設定項目 | 現場での推奨設定値 | 設計の理由・意図 |
|---|---|---|
| 最初のエラー | サービスの再起動 | 1回目の突発的なクラッシュは即座に自動復旧させる |
| 2回目のエラー | サービスの再起動 | 一時的なリソース競合を考慮し、2回目までは再起動を試みる |
| その後のエラー | 何もしない(またはプログラムの実行) | 3回連続で落ちる場合は設定不備や致命的障害 のため、無限再起動ループを止める |
| エラー カウントのリセット | 1 日後(86400秒) |
1日安定稼働すればエラー回数を0にリセットする(初期値 0 は絶対NG) |
| サービスの再起動 | 1 分後(60000ミリ秒) |
クラッシュ直後のポート解放やファイルロック解除を待つため、1分のクールダウンを置く |
2. sc.exe failure コマンドによる一括設定手順
複数台のサーバーやキッティング手順書で設定を標準化する場合は、標準の sc.exe コマンド(管理者権限)を使ってコマンドラインから設定します。
【注意】 PowerShell上で
scとだけ打つとSet-Contentエイリアスとして解釈されるため、必ず拡張子付きのsc.exeと記述してください。
# 現在のサービスの回復設定を確認する(例:Spoolerサービス)
sc.exe qfailure "Spooler"
# 1回目:60秒後に再起動 / 2回目:60秒後に再起動 / 3回目以降:何もしない / リセット期間:86400秒(1日) に設定する
sc.exe failure "Spooler" reset= 86400 actions= restart/60000/restart/60000/""/0
# 正常終了以外のエラーコードで停止した際も回復アクションを発動させるフラグを有効化
sc.exe failureflag "Spooler" 1
コマンド内のパラメータの意味は以下の通りです。
- reset= 86400: エラー回数のカウンターをリセットする秒数(86400 秒 = 24時間)。※ = の直後に半角スペースが必須です。
- actions= restart/60000/restart/60000/""/0: スラッシュ区切りで「1回目の動作/待機ミリ秒/2回目の動作/待機ミリ秒/3回目の動作/待機ミリ秒」を指定します。""/0 は「何もしない」を意味します。
現場でハマる「サービス自動回復」3つの落とし穴
自動再起動を設定したつもりが「いざという時に動かなかった」「逆にサーバーを高負荷にしてしまった」という現場特有の落とし穴を3つ紹介します。
落とし穴1:「エラーカウントのリセット」を「0日」のままにする罠
GUIの「回復」タブで、最初のエラーを「サービスの再起動」、その後のエラーを「何もしない」に設定した際、「エラー カウントのリセット: 0 日後」の初期値のままOKを押してしまうミスが非常に多く見られます。
リセット期間が 0 のままだと、サーバーが起動してから過去に2回でもクラッシュした履歴があると、数ヶ月後に起きた3回目のクラッシュが「その後のエラー(何もしない)」と判定され、自動再起動が発動しなくなります。リセット期間には必ず 1 日(86400 秒)以上を指定してください。
落とし穴2:「その後のエラー」まで再起動にして無限ループを引き起こす
1回目・2回目だけでなく「その後のエラー」まで「サービスの再起動(待機0分)」に設定すると、設定ファイルの破損やDBサーバーの計画停止などでサービスが起動できなくなった際、1秒間に何十回も「起動→即クラッシュ→7031出力」を繰り返す無限再起動ループ に陥ります。
これによりCPU使用率が張り付き、システムイベントログが7031で埋め尽くされて重要な他ログが流出してしまいます。「3回目(その後のエラー)は何もしない」にして監視アラートで人間が介入する設計にしておくのが安全です。
落とし穴3:プロセスは死んでいないが「エラー終了」した時に回復が動かない
既定では、サービスの回復アクションは「services.exe(SCM)から見て、サービスプロセス(.exe)が突然消滅した(クラッシュした)とき」にしか発動しません。
もしサービスプログラムが内部でエラーを検知し、自ら行儀よく停止処理を行ってエラーコードを返した場合(イベントID 7023等)、SCMは「プロセスは正常な手順で終了した」とみなして自動再起動を行いません。これを防ぐには、前述の sc.exe failureflag "<サービス名>" 1(GUIでは「エラーで停止したときに回復アクションを有効にする」チェックボックス)をオンにする必要があります。
よくある質問(FAQ)
Q: イベントID 7031でサービスが自動再起動された後、再起動が成功したかどうかはどのイベントIDで確認できますか?
A: システムログの イベントID 7036(ソース:Service Control Manager)で確認できます。イベントID 7031が記録された指定ミリ秒(例:1分後)のタイムスタンプで、「<サービス名> サービスは 実行中 状態に入りました」というイベントID 7036が記録されていれば、自動再起動による復旧は成功しています。
Q: 依存関係があるサービス(親サービス)が7031で落ちた場合、子サービスも一緒に再起動されますか?
A: いいえ、親サービスが突然クラッシュして自動再起動された場合でも、それに依存する子サービスは自動的には再起動されず、通信切断や不整合エラーを起こすことがあります。親子関係があるサービス群を確実に連動復旧させたい場合は、回復アクションで「サービスの再起動」ではなく「プログラムの実行」を選び、親サービスと子サービスを順番に Restart-Service するバッチ/PowerShellスクリプトを呼び出す構成が推奨されます。
Q: 原因調査のためにクラッシュ時のメモリダンプ(.dmp)を確実に取得するにはどうすればいいですか?
A: レジストリの HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\<サービスの実行ファイル名.exe> キーを作成し、DumpFolder(保存先パス)と DumpType(2 =フルダンプ)を設定しておくことで、次回イベントID 7031(およびApplication ID 1000)が発生した瞬間に自動でプロセスダンプを出力させることができます。
まとめ
Windowsサービスの異常終了(イベントID 7031)への対応と自動回復設計のポイントは以下の通りです。
- システムログの イベントID 7031は「結果」 であり、クラッシュの直接原因は同時刻の Applicationログ(イベントID 1000 / 1026) から特定する
- 重要な常駐サービスには「回復」設定を行い、1回目・2回目は 1分待ってから「サービスの再起動」、3回目以降は無限ループ防止のため 「何もしない」 に設定する
- カウンターが蓄積して自動復旧が不発になるのを防ぐため、「エラーカウントのリセット期間」は必ず1日(86400秒)以上 に設定する
- 複数サーバーへの展開には
sc.exe failureとsc.exe failureflagコマンドを活用して設定ミスをなくす
ログの相関分析と適切な自動回復設定を組み合わせておくことで、突発的なプロセスクラッシュにも強い安定したシステム運用を実現できます。
関連記事
この記事で提供される情報は、一般的なガイダンスを目的としており、すべての環境やシステムでの動作を保証するものではありません。
OSのバージョンやリリースによっては、記載されている事が実行できない、または異なる結果をもたらす可能性があります。
また、会社所有のパソコン、スマホ、タブレットなどでは、ポリシーや権限によって実行できない場合があります。
この記事の情報を使用することによって生じる問題や結果について、筆者およびサイト管理者は責任を負いません。
すべての操作は自己責任で行ってください。
またお会いしましょう!
著者のおすすめ教材 & note実践記事
PowerShell実務スクリプト50選
AD・Windows運用・障害対応をコマンド一発で自動化する現役SEの実務スクリプト集。
ググっても出ない実務テク20選
社内SE現場の地味で細かすぎる面倒作業を一撃で解消する実践テクニック集。