【bat】バッチファイルでプロセスを監視して異常終了を検知する完全ガイド|tasklist・監視ループ・複数プロセス・終了コード・自動復旧まで

【bat】バッチファイルでプロセスを監視して異常終了を検知する完全ガイド|tasklist・監視ループ・複数プロセス・終了コード・自動復旧まで bat

業務システムやバックグラウンドサービスが知らぬ間に落ちていた——そんな事態を防ぐにはプロセスの継続的な監視が有効です。専用の監視ツールがなくても、バッチファイルだけで「プロセスの生存確認→異常をログに記録→ポップアップ通知→自動再起動」まで実装できます。

この記事でわかること

  • tasklist でプロセスの生存を確認してログに記録する基本
  • 定間隔の監視ループで継続的にプロセスをチェックする方法
  • 複数プロセスを1本のバッチで同時監視する方法
  • wmic でプロセスのメモリ使用量を監視する方法
  • start /wait で終了コードを記録する方法
  • 異常検知時の段階的対応(ログ→通知→自動再起動)
スポンサーリンク

プロセス監視の方法比較

方法 コマンド 生存確認 メモリ/CPU監視 終了コード取得
tasklist + findstr tasklist | findstr /i “app.exe”
wmic process wmic process where Name=”app.exe” ○(WorkingSetSize)
start /wait start /wait “” app.exe —(起動後に待機) ○(%ERRORLEVEL%)
PowerShell Get-Process -Name app -EA SilentlyContinue ○(CPU/RAM詳細)
tasklist vs wmic の使い分け
tasklist | findstr は高速でシンプルですが、プロセス名の部分一致で誤検出するリスクがあります。wmic process where "Name='app.exe'" は完全一致で検索できるため確実です。メモリ使用量なども取得したい場合は wmic か PowerShell を使います。

基本:tasklist でプロセス生存確認してログに記録する

基本: プロセス存在チェック + タイムスタンプ付きログ記録
@echo off
setlocal

set TARGET=myapp.exe
set LOGFILE=C:\logs\proc_monitor.log
if not exist "C:\logs" mkdir "C:\logs"

REM タイムスタンプ整形
set T=%TIME: =0%
set TS=%DATE% %T:~0,8%

REM /FI でフィルタリング: IMAGENAME が一致するプロセスのみ
tasklist /FI "IMAGENAME eq %TARGET%" 2>nul | findstr /i "%TARGET%" >nul
if %ERRORLEVEL% equ 0 (
    echo [%TS%] [OK] %TARGET% 動作中 >> "%LOGFILE%"
) else (
    echo [%TS%] [NG] %TARGET% が停止しています! >> "%LOGFILE%"
)
endlocal
tasklist /FI を使う理由
tasklist | findstr "app.exe" の代わりにtasklist /FI "IMAGENAME eq app.exe" を使うと完全一致(IMAGENAME が app.exe のプロセスのみ)でフィルタリングできます。findstr "app" では “myapp.exe”・”app_helper.exe” など別プロセスも誤マッチするリスクがあります。tasklist コマンドの詳細な使い方はプロセスの終了を待つ全方法まとめも参照してください。

監視ループ:定間隔でプロセスを継続チェックする

バッチファイルを常駐させてプロセスを定期的に監視します。timeout で指定秒数待機してから再チェックするループ構造が基本です。

監視ループ: 30秒ごとにプロセスをチェック
@echo off
setlocal enabledelayedexpansion

set TARGET=myapp.exe
set LOGFILE=C:\logs\proc_monitor.log
set INTERVAL=30
if not exist "C:\logs" mkdir "C:\logs"

call :log "===== 監視開始 対象: %TARGET% ====="

:MONITOR_LOOP
tasklist /FI "IMAGENAME eq %TARGET%" 2>nul | findstr /i "%TARGET%" >nul
if %ERRORLEVEL% equ 0 (
    call :log "[OK] %TARGET% 動作中"
) else (
    call :log "[NG] %TARGET% 停止検知!"
)
timeout /t %INTERVAL% /nobreak >nul
goto MONITOR_LOOP

:log
set T=%TIME: =0%
echo [%DATE% %T:~0,8%] %~1 >> "%LOGFILE%"
echo [%DATE% %T:~0,8%] %~1
goto :eof
監視ループはコマンドプロンプトウィンドウが開き続けます
このバッチを実行するとウィンドウが常駐します。バックグラウンド実行したい場合はタスクスケジューラで「ユーザーがログオンしているかどうかにかかわらず実行する」に設定するか、start /min "" monitor.bat で最小化して起動してください。Ctrl+C で監視ループを停止できます。

複数プロセスを1本のバッチで同時監視する

監視対象のプロセス名をリスト化し、for ループで順番にチェックします。停止しているプロセスをカウントして、全プロセスの状態を1回の実行でまとめて記録できます。

複数プロセスを一括監視してサマリーをログに記録
@echo off
setlocal enabledelayedexpansion

set LOGFILE=C:\logs\multi_proc.log
set INTERVAL=60
if not exist "C:\logs" mkdir "C:\logs"

REM 監視対象プロセスをスペース区切りで列挙
set TARGETS=svchost.exe notepad.exe myapp.exe

:MULTI_LOOP
set T=%TIME: =0%
set TS=%DATE% %T:~0,8%
set NG_COUNT=0

echo ===== チェック: %TS% ===== >> "%LOGFILE%"

for %%P in (%TARGETS%) do (
    tasklist /FI "IMAGENAME eq %%P" 2>nul | findstr /i "%%P" >nul
    if !ERRORLEVEL! equ 0 (
        echo   [OK] %%P >> "%LOGFILE%"
    ) else (
        echo   [NG] %%P 停止! >> "%LOGFILE%"
        set /a NG_COUNT+=1
    )
)

if %NG_COUNT% gtr 0 (
    echo 異常プロセス数: %NG_COUNT% 件 >> "%LOGFILE%"
)
echo. >> "%LOGFILE%"

timeout /t %INTERVAL% /nobreak >nul
goto MULTI_LOOP

wmic でメモリ使用量も含めて監視する

プロセスが「存在するが異常に多くのメモリを消費している」状態もwmicで検知できます。メモリリークや高負荷による異常を捉えるのに有効です。

wmic でプロセスのメモリ使用量を取得してチェック
@echo off
setlocal enabledelayedexpansion

set TARGET=myapp.exe
set LOGFILE=C:\logs\mem_monitor.log
REM メモリ上限(バイト): 500 MB = 524288000
set MEM_LIMIT=524288000
if not exist "C:\logs" mkdir "C:\logs"

:MEM_LOOP
set T=%TIME: =0%
set TS=%DATE% %T:~0,8%

REM プロセスの存在確認
tasklist /FI "IMAGENAME eq %TARGET%" 2>nul | findstr /i "%TARGET%" >nul
if %ERRORLEVEL% neq 0 (
    echo [%TS%] [NG] %TARGET% 停止! >> "%LOGFILE%"
    goto MEM_WAIT
)

REM WorkingSetSize(バイト)を取得
set MEM=0
for /f "skip=1 tokens=2 delims==" %%M in (
    'wmic process where "Name='%TARGET%'" get WorkingSetSize /value'
) do (
    if not "%%M"=="" set MEM=%%M
)

set /a MEM_MB=%MEM% / 1048576

if %MEM% gtr %MEM_LIMIT% (
    echo [%TS%] [WARN] %TARGET% メモリ使用量超過: !MEM_MB! MB >> "%LOGFILE%"
) else (
    echo [%TS%] [OK] %TARGET% メモリ: !MEM_MB! MB >> "%LOGFILE%"
)

:MEM_WAIT
timeout /t 60 /nobreak >nul
goto MEM_LOOP
WorkingSetSize はプロセスが実際に使用している物理メモリ量
WorkingSetSize はプロセスが現在使用している物理メモリ(RAM)をバイト単位で返します。タスクマネージャーの「メモリ(プライベート ワーキング セット)」に相当します。1 MB = 1,048,576 バイトで、set /a MEM_MB=MEM / 1048576 で MB 換算できます。ただし set /a は 2 GB 上限があるため、大量メモリを使うプロセスには PowerShell を使ってください。

start /wait で終了コードを記録する

プロセスをバッチから起動して終了コードを記録することで、「正常終了(0)」か「異常終了(1以上)」かを後から確認できます。定期実行バッチがエラーで落ちた理由の追跡に有効です。

start /wait で起動し終了コードをログに記録
@echo off
setlocal

set APP=C:\apps\myapp.exe
set LOGFILE=C:\logs\exitcode.log
if not exist "C:\logs" mkdir "C:\logs"

:RUN_LOOP
set T=%TIME: =0%
echo [%DATE% %T:~0,8%] %APP% 起動 >> "%LOGFILE%"

REM start /wait でプロセス終了まで待機
start /wait "" "%APP%"
set EXIT_CODE=%ERRORLEVEL%

set T=%TIME: =0%
if %EXIT_CODE% equ 0 (
    echo [%DATE% %T:~0,8%] [OK] 正常終了 EXITCODE=%EXIT_CODE% >> "%LOGFILE%"
) else (
    echo [%DATE% %T:~0,8%] [NG] 異常終了 EXITCODE=%EXIT_CODE% >> "%LOGFILE%"
    REM 異常終了時は10秒待って再起動
    timeout /t 10 /nobreak >nul
    goto RUN_LOOP
)

echo 処理完了
endlocal
start /wait と ERRORLEVEL の注意点
start /wait でバッチから外部 exe を起動した場合、終了後の %ERRORLEVEL% に終了コードが格納されます。ただし bat ファイルを start /wait "" script.bat で呼び出した場合、bat の終了コードは親バッチの ERRORLEVEL に反映されません(0 が返る)。bat の終了コードを伝播させるには call を使うか、ファイルや環境変数を介して結果を受け渡してください。

段階的対応:ログ→ポップアップ通知→自動再起動

異常検知後の対応を段階的に実装します。「まずログに記録 → 画面通知 → 自動再起動 → 再起動が続く場合は監視停止」のフローが実運用で使いやすいパターンです。

段階的対応: ログ→msg通知→自動再起動(最大3回)
@echo off
setlocal enabledelayedexpansion

set TARGET=myapp.exe
set APP_PATH=C:\apps\myapp.exe
set LOGFILE=C:\logs\watchdog.log
set INTERVAL=30
set MAX_RESTART=3
set RESTART_COUNT=0
if not exist "C:\logs" mkdir "C:\logs"

call :log "===== ウォッチドッグ開始 ====="

:WATCHDOG
tasklist /FI "IMAGENAME eq %TARGET%" 2>nul | findstr /i "%TARGET%" >nul
if %ERRORLEVEL% equ 0 (
    call :log "[OK] %TARGET% 動作中"
    set RESTART_COUNT=0
    goto WATCHDOG_WAIT
)

REM --- 異常検知 ---
set /a RESTART_COUNT+=1
call :log "[NG] %TARGET% 停止検知 (再起動: !RESTART_COUNT!/%MAX_RESTART%)"

if !RESTART_COUNT! gtr %MAX_RESTART% (
    call :log "[ABORT] 再起動上限到達。監視を停止します。"
    msg * "%TARGET% の再起動が上限に達しました。手動確認してください。"
    exit /b 1
)

REM ポップアップ通知(ログオン中ユーザーへ)
msg * "[監視] %TARGET% が停止しました。自動再起動します。"

REM 自動再起動
start "" "%APP_PATH%"
call :log "[INFO] %TARGET% を再起動しました"

:WATCHDOG_WAIT
timeout /t %INTERVAL% /nobreak >nul
goto WATCHDOG

:log
set T=%TIME: =0%
echo [%DATE% %T:~0,8%] %~1 >> "%LOGFILE%"
echo [%DATE% %T:~0,8%] %~1
goto :eof
msg コマンドについて
msg * はコンソールセッションにメッセージウィンドウをポップアップ表示します。Windows 10/11 の Home エディションでは動作しない場合があります(Pro/Enterprise 向け機能)。Home エディション環境では代わりに powershell -Command "[System.Windows.Forms.MessageBox]::Show('メッセージ')" または通知ファイルをデスクトップに作成するなどの方法で代替できます。自動再起動の詳細なパターンは一定時間ごとに指定アプリを自動で再起動するスクリプトも参照してください。
関連記事
プロセスの終了を「待つ」パターンはプロセスの終了を待つ全方法まとめ、ネットワーク接続の監視・再接続はネットワーク接続を監視して異常検知・再接続する方法、ログへの時刻記録は実行時刻・経過時間をログに記録する完全ガイドを参照してください。

まとめ

  • 存在確認: tasklist /FI "IMAGENAME eq app.exe" で完全一致チェック
  • 監視ループ: :LOOP → tasklist → timeout → goto LOOP の構造で継続監視
  • 複数プロセス: for %%P in (a.exe b.exe) で一括チェック・NG件数を集計
  • メモリ監視: wmic process where Name=... get WorkingSetSize で使用量を閾値チェック
  • 終了コード記録: start /wait "" app.exe 後に %ERRORLEVEL% を記録
  • 段階的対応: ログ記録 → msg 通知 → 自動再起動 → 上限到達で監視停止

関連記事: プロセスの終了を待つ全方法まとめ / 指定アプリを自動再起動するスクリプト / バッチファイルでログを出力する完全ガイド

よくある質問(FAQ)

Qtasklist でプロセスを検索すると同名の別プロセスも引っかかります。
Atasklist | findstr "app.exe" は部分一致で、”myapp.exe” や “app.exe.config” も一致します。tasklist /FI "IMAGENAME eq app.exe" を使うとプロセス名が完全一致するものだけ返ります。さらに PID も特定したい場合は tasklist /FI "IMAGENAME eq app.exe" /FO CSV でCSV形式に出力すると for /f でパースしやすくなります。
Q監視バッチを止めると一緒に監視対象アプリも終了してしまいます。
A監視バッチが start /wait でアプリを起動している場合、バッチを止めるとアプリも止まります。監視対象を独立して起動するには start "" "app.exe"(/wait なし)で起動し、別のウィンドウ(プロセス)として動かします。その後監視バッチだけ別途起動して tasklist でチェックする構成にしてください。
Qプロセスが「応答なし(ハング)」状態のとき、tasklist では動作中と判定されます。
Atasklist はプロセスの存在だけを確認するため、ハング状態のプロセスも「動作中」と判定します。応答確認が必要な場合は①定期的な出力ファイルのタイムスタンプを確認する、②PowerShell の Get-ProcessResponding プロパティを確認する、③専用の HTTP ヘルスチェックエンドポイントに curl でアクセスして応答を確認する、などの方法を組み合わせてください。
Qサービス(Windows Service)のプロセスを監視したいです。
AWindowsサービスは sc query サービス名 で状態を確認できます。sc query MySvc | findstr "RUNNING" が空なら停止中です。停止したサービスを再起動するには sc start MySvc または net start MySvc を使います。サービスの起動・停止操作の詳細は関連記事も合わせて参照してください。
Qwmic が Windows 11 で「非推奨」と表示されます。代替手段はありますか?
AWindows 11 では wmic が非推奨になりました。代替として PowerShell の Get-Process -Name "myapp" -ErrorAction SilentlyContinue でプロセス情報を取得できます。メモリ使用量は .WorkingSet(バイト)、CPU時間は .TotalProcessorTime で取得できます。バッチから呼び出す場合は powershell -NoProfile -Command "..." を使います。