【bat】tasklistでプロセス監視|異常終了検知・自動再起動

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

batでプロセス監視をするなら、基本は tasklist /FI "IMAGENAME eq app.exe" で対象プロセスの存在を確認し、停止していたらログ出力・通知・自動再起動へ進める形です。専用監視ツールがなくても、簡易的な異常終了検知ならバッチファイルだけで実装できます。

この記事では、まず tasklist による生存確認、監視ループ、複数プロセス監視、start /wait の終了コード記録、停止時の自動再起動まで、実務で使いやすい順に整理します。

先に結論:存在確認は tasklist /FI "IMAGENAME eq myapp.exe"、継続監視は timeoutgoto のループ、異常時はログ→通知→再起動の順で段階的に対応します。

スポンサーリンク

プロセス監視でよく使う書き方早見表

目的 書き方 使いどころ
プロセス存在確認 tasklist /FI "IMAGENAME eq app.exe" 最も基本の生存確認
停止判定 findstr /i "app.exe" >nul ERRORLEVEL で分岐
定期監視 timeout /t 30 + goto LOOP 30秒ごとなどに繰り返す
複数プロセス監視 for %%P in (a.exe b.exe) 対象をまとめて確認
終了コードを記録 start /wait "" "app.exe" 起動したアプリの終了結果を見る
CPU・メモリ監視 typeperf / PowerShell 存在確認だけでは足りない場合
異常時に再起動 start "" "app.exe" 停止検知後に自動復旧
タスク化 schtasks /create ... ログオンしていない環境で実行
最小テンプレート
@echo off
setlocal

set "TARGET=myapp.exe"
set "APP_PATH=C:\apps\myapp.exe"

tasklist /FI "IMAGENAME eq %TARGET%" 2>nul | findstr /i "%TARGET%" >nul
if errorlevel 1 (
    echo %TARGET% が停止しています。再起動します。
    start "" "%APP_PATH%"
    exit /b 1
)

echo %TARGET% は動作中です。
exit /b 0

目的別ショートカット

やりたいこと 読む場所 主なコマンド
まず書き方だけ知りたい 書き方早見表 tasklist /FI
監視方法を比較したい 方法比較 tasklist / wmic
プロセス停止をログに残したい 基本チェック findstr / ログ出力
常時監視したい 監視ループ timeout / goto
複数プロセスをまとめたい 複数プロセス監視 for
異常終了後に自動復旧したい 段階的対応 ログ / 通知 / 自動再起動
終了コードを見たい 終了コード記録 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('メッセージ')" または通知ファイルをデスクトップに作成するなどの方法で代替できます。自動再起動の詳細なパターンは一定時間ごとに指定アプリを自動で再起動するスクリプトも参照してください。
関連記事
プロセスの終了を「待つ」パターンはプロセスの終了を待つ全方法まとめ、ネットワーク接続の監視・再接続はネットワーク接続を監視して異常検知・再接続する方法、ログへの時刻記録は実行時刻・経過時間をログに記録する完全ガイドを参照してください。

あわせて確認したい関連記事

よくある質問

Qbatでプロセスが起動しているか確認するには?
Atasklist /FI "IMAGENAME eq app.exe" を実行し、findstrERRORLEVEL で判定します。部分一致を避けるため、まず /FI で絞り込むのがおすすめです。
Qtasklistで停止を検知したら自動再起動できますか?
Aできます。停止判定の分岐で start "" "C:\apps\app.exe" を実行します。再起動回数に上限を設け、連続失敗時はログ出力して停止する設計にすると安全です。
Q監視ループはどう書きますか?
A:LOOP ラベル、tasklisttimeout /t 30 /nobreakgoto LOOP を組み合わせます。短すぎる間隔はPC負荷やログ肥大の原因になります。
Qプロセスが応答なしでもtasklistでは動作中になります。
Atasklistは存在確認だけです。ハング検知には、出力ファイルの更新時刻、HTTPヘルスチェック、PowerShellの Responding、CPU・メモリ使用率の監視を組み合わせてください。
Q複数プロセスを監視するには?
Afor %%P in (a.exe b.exe c.exe) do (...) で対象名を回し、プロセスごとに tasklist /FI を実行します。NG件数を集計して最後に通知すると運用しやすくなります。
Q終了コードを記録するには?
Aバッチから起動したアプリなら start /wait "" "app.exe" のあとに%ERRORLEVEL% をログへ書きます。すでに起動済みのプロセスをtasklistで監視するだけでは終了コードは取得できません。
Qタスクスケジューラで監視バッチを常駐できますか?
Aできます。長時間動かす場合は「ユーザーがログオンしているかどうかにかかわらず実行する」や、再起動時の自動開始、ログ保存先の権限を確認してください。
Qwmicが使えない環境ではどうしますか?
AWindows 11ではwmicが非推奨です。CPU・メモリ監視が必要なら typeperf、PowerShellの Get-Process、またはパフォーマンスカウンターを使う方法へ切り替えてください。

まとめ

  • 存在確認: 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 通知 → 自動再起動 → 上限到達で監視停止

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