【bat】exit /bの使い方|ERRORLEVEL・終了コードを返す方法

【bat】EXIT /B 完全解説|/B オプション・戻り値 0/1・ウィンドウを閉じない仕組みと活用パターン bat

batで処理結果を呼び出し元へ返すなら、基本は exit /b 終了コード です。exit だけを書くとコマンドプロンプトごと閉じることがありますが、exit /b は現在のバッチやサブルーチンだけを終了し、ERRORLEVEL に成功・失敗の番号を残せます。

この記事では exit /b 0exit /b 1 の違い、ERRORLEVEL の受け取り方、タスクスケジューラで失敗扱いにする終了コード、GOTO :EOF との使い分けまで、実務で迷いやすいポイントを整理します。

この記事で学べること

  • EXITEXIT /B の違い(ウィンドウが閉じない理由)
  • EXIT /B 0(成功)と EXIT /B 1(失敗)の慣習と使い分け
  • ERRORLEVEL の正しい受け取り方(比較の落とし穴)
  • 戻り値を活用したサブルーチン・別バッチ呼び出しの設計
  • タスクスケジューラ・CI/CD との連携パターン
  • 負の値・特殊ケースと注意点

先に結論:成功なら exit /b 0、失敗なら exit /b 1 以上を返します。別バッチを呼ぶときは call の直後に set "RC=%ERRORLEVEL%" で退避してから判定すると安全です。
スポンサーリンク

まず使う書き方早見表

やりたいこと 書き方 使いどころ
正常終了を返す exit /b 0 最後まで成功したことを呼び出し元へ返す
失敗終了を返す exit /b 1 エラー時にタスクやCIを失敗扱いにする
失敗理由を分ける exit /b 2 / exit /b 3 引数エラー、ファイルなし、通信失敗などを区別する
直前の終了コードを返す exit /b 直前コマンドの結果をそのまま返したいとき
呼び出し元で受け取る set "RC=%ERRORLEVEL%" call 直後に値を保存する
終了コードを比較する if "%RC%"=="0" ... IF ERRORLEVEL の「N以上」判定を避ける
最小テンプレート
@echo off
setlocal

call :main
set "RC=%ERRORLEVEL%"

if not "%RC%"=="0" (
    echo [ERROR] 処理に失敗しました。終了コード=%RC%
    exit /b %RC%
)

echo [OK] 処理が完了しました。
exit /b 0

:main
rem ここに実処理を書く
exit /b 0

目的別ショートカット

目的 読む場所 主なキーワード
exitexit /b の違いを知りたい EXIT /B とは? /B オプションの意味 ウィンドウを閉じない、呼び出し元へ戻る
正しい構文だけ先に確認したい EXIT /B の構文 exit /b [終了コード]
exit /b 0exit /b 1 を使い分けたい EXIT /B 0 と EXIT /B 1 の意味 0=成功、1以上=失敗
ERRORLEVEL を受け取りたい ERRORLEVEL で戻り値を受け取る callset RC
サブルーチンで使いたい 戻り値を活用した設計パターン call :label、戻り値設計
タスクスケジューラで失敗扱いにしたい タスクスケジューラ・CI/CD との連携 最後の実行結果、終了コード

EXIT /B とは? /B オプションの意味

EXIT /B/B「Batch(バッチ)の現在のコンテキストだけ終了する」 オプションです。

コマンド 動作 ウィンドウ 呼び出し元
EXIT cmd.exe プロセス自体を終了 閉じる 戻らない
EXIT /B 現在のバッチ/サブルーチンを終了 閉じない 戻る
EXIT /B 0 同上 + 戻り値に 0 をセット 閉じない 戻る
EXIT /B 1 同上 + 戻り値に 1 をセット 閉じない 戻る
なぜ「閉じない」のか?
コマンドプロンプトを手動で開いて .bat を実行した場合、EXIT(/B なし)は cmd.exe ごと終了するためウィンドウが消えます。
EXIT /B ならバッチスクリプト内のコンテキストだけを抜けるため、ウィンドウはそのまま残ります。
スケジューラから呼ぶ場合も /B を付けることで、プロセスが正常に終了コードを親プロセスに返せます。

EXIT /B の構文

EXIT [/B] [exitCode]
パラメータ 省略時の動作 指定時の動作
/B cmd.exe プロセスを終了 現在のバッチコンテキストのみ終了
exitCode 直前コマンドの ERRORLEVEL を引き継ぐ 指定した整数値を ERRORLEVEL にセット
exitCode を省略すると危険なケースがある
EXIT /B(数値なし)は直前コマンドの ERRORLEVEL をそのまま返します。
意図せずエラーコードを伝播させたくない場合は 必ず EXIT /B 0EXIT /B 1 と明示してください。

EXIT /B 0 と EXIT /B 1 の意味(戻り値の慣習)

戻り値(終了コード)には以下の慣習があります。これは Windows のシステムコマンドや多くのプログラムが従う標準です。

意味 用途例
0 正常終了(成功) 処理が問題なく完了した
1 一般エラー 何か失敗した(理由は問わない簡易エラー)
2 コマンドミス・引数不正 使い方が間違っている
3〜9 カスタムエラー 自前バッチの独自エラー区分に使う
10〜127 アプリ定義エラー ツール独自の詳細エラーコード
128〜255 プロセス異常終了系 シグナル終了(バッチでは稀)
成功・失敗を返す基本例
@echo off
setlocal

call :Process
set "RC=%ERRORLEVEL%"

if "%RC%"=="0" (
    echo 処理成功
) else (
    echo 処理失敗(終了コード: %RC%)
)
exit /b %RC%

:Process
xcopy /Y "C:\source\*" "D:\dest\" >nul 2>&1
if errorlevel 1 exit /b 1
exit /b 0

ERRORLEVEL で戻り値を受け取る

EXIT /B N でセットした値は呼び出し元で %ERRORLEVEL% または IF ERRORLEVEL で受け取れます。

方法1:%ERRORLEVEL% 変数で比較(推奨)

CALL :MyFunc
if %ERRORLEVEL% EQU 0 echo 成功
if %ERRORLEVEL% EQU 1 echo 失敗
if %ERRORLEVEL% EQU 2 echo 引数エラー

方法2:IF ERRORLEVEL N(旧構文・注意が必要)

CALL :MyFunc
IF ERRORLEVEL 2 echo 2以上
IF ERRORLEVEL 1 echo 1以上(2以上も含む!)
IF ERRORLEVEL 0 echo 0以上(常に真!)
IF ERRORLEVEL N は「N 以上」の判定
IF ERRORLEVEL 1 は「ERRORLEVEL が 1 以上」を意味します。EQU 1(ちょうど1)ではありません。
複数コードを区別する場合は 大きい値から順に判定するか、%ERRORLEVEL% EQU N 形式を使ってください。

方法3:ERRORLEVEL を変数に退避してから比較(最安全)

CALL の直後に別コマンドを挟むと ERRORLEVEL が上書きされます。安全のため変数に退避しましょう。

ERRORLEVELを退避して比較する例
call :MyFunc
set "RC=%ERRORLEVEL%"

echo 戻り値: %RC%
if "%RC%"=="0" echo 成功処理
if not "%RC%"=="0" echo エラー処理(code=%RC%)

EXIT /B と GOTO :EOF の違い

どちらも「現在のコンテキストを終了して戻る」命令ですが、動作に微妙な差があります。

命令 ERRORLEVEL SETLOCAL との相性 推奨度
EXIT /B 0 0 を明示セット ENDLOCAL を自動実行 ★★★ 最推奨
EXIT /B 直前の値を引き継ぎ ENDLOCAL を自動実行 ★★☆ 省略可だが明示推奨
GOTO :EOF 変更しない ENDLOCAL を自動実行 ★★☆ 旧来の書き方

戻り値を活用した設計パターン

パターン1:成否だけを返す(0/1)

最もシンプルな設計。成功=0・失敗=1 のみ。

:CopyFiles
  xcopy /Y "%~1" "%~2" >nul 2>&1
  if %ERRORLEVEL% NEQ 0 EXIT /B 1
  EXIT /B 0

パターン2:複数の失敗理由を区別する(0/1/2/3)

処理の失敗原因を呼び出し元が判断できるよう、コードを細分化します。

:BackupFile
  :: 引数チェック
  if "%~1"=="" EXIT /B 2
  :: ファイル存在チェック
  if not exist "%~1" EXIT /B 3
  :: バックアップ実行
  copy "%~1" "%~1.bak" >nul 2>&1
  if %ERRORLEVEL% NEQ 0 EXIT /B 1
  EXIT /B 0

:: 呼び出し側
CALL :BackupFile "C:\data\log.txt"
set RC=%ERRORLEVEL%
if %RC% EQU 0 echo バックアップ成功
if %RC% EQU 1 echo コピー失敗
if %RC% EQU 2 echo 引数が未指定
if %RC% EQU 3 echo ファイルが見つからない

パターン3:別バッチを CALL して戻り値を受け取る

サブルーチンだけでなく、別ファイルのバッチを CALL したときも同様に戻り値を受け取れます。

CALL を付けないと戻り値が取れない
process.bat(CALL なし直接実行)や START process.bat では ERRORLEVEL が親バッチに返ってきません。
必ず CALL process.bat の形で呼び出してください。
:: main.bat
@echo off
CALL process.bat
set RC=%ERRORLEVEL%
if %RC% NEQ 0 (
  echo process.bat が失敗しました(code: %RC%)
  EXIT /B 1
)
echo 全処理完了
EXIT /B 0
:: process.bat
@echo off
echo 処理中...
:: 何らかの理由で失敗
EXIT /B 1

負の値・特殊ケース

EXIT /B に負の値を渡すと?

EXIT /B に負の値を渡すと、ERRORLEVEL には 符号なし 32bit 整数として格納されます。

EXIT /B -1
:: → ERRORLEVEL = 4294967295 (0xFFFFFFFF)

EXIT /B -2
:: → ERRORLEVEL = 4294967294
負の値は使用しないことを推奨
if %ERRORLEVEL% EQU -1 では判定できません(変数には正の値が格納されるため)。
IF ERRORLEVEL 1 は 4294967295 でも通るため、一見エラー扱いになりますが、値の比較には使えません。
終了コードは 0〜9 の範囲に収めるのが実務的なベストプラクティスです。

実務で迷ったときの終了コード設計

終了コードは細かく増やしすぎると運用が面倒になります。まずは 0=成功1=一般的な失敗2=引数や設定の不備3=入力ファイルなし くらいに分けると、ログやタスクスケジューラの結果から原因を追いやすくなります。

終了コードを分ける例
@echo off
setlocal

if "%~1"=="" (
    echo [ERROR] 引数が指定されていません。
    exit /b 2
)

if not exist "%~1" (
    echo [ERROR] 入力ファイルが見つかりません: "%~1"
    exit /b 3
)

rem 実処理
echo [OK] 入力ファイルを確認しました: "%~1"
exit /b 0

タスクスケジューラ・CI/CD との連携

バッチファイルを定期実行する場合、EXIT /B で返した終了コードが外部ツールに伝わります。

タスクスケジューラ

:: backup.bat の最後
if %ERRORLEVEL% NEQ 0 EXIT /B 1
EXIT /B 0

タスクスケジューラでは「最後の実行結果」に終了コードが表示されます。0 以外はエラー扱いになり、アラート設定が可能です。

Jenkins・GitHub Actions など CI/CD

:: Jenkins で bat ステップとして実行する場合
@echo off
CALL build.bat
if %ERRORLEVEL% NEQ 0 (
  echo BUILD FAILED
  EXIT /B 1
)
echo BUILD SUCCESS
EXIT /B 0

CI ツールはプロセスの終了コードが 0 以外の場合にビルドを「失敗」として扱います。EXIT /B 0 を書き忘れると、直前コマンドの ERRORLEVEL によって誤って失敗扱いになるケースに注意してください。

よくあるハマりポイント一覧

症状 原因 解決策
ウィンドウが突然閉じる EXIT(/B なし)を使っている EXIT /B に変更する
戻り値が常に 0 以外になる EXIT /B の直前に失敗コマンドがある 明示的に EXIT /B 0 と書く
IF ERRORLEVEL 1 が常に真になる IF ERRORLEVEL N は「N以上」の判定 if %ERRORLEVEL% EQU 1 を使う
CALL直後のERRORLEVELが変わる echo などのコマンドが ERRORLEVEL を上書き CALL 直後に set RC=%ERRORLEVEL% で退避
別バッチの戻り値が取れない CALL せず直接実行・START で起動している CALL process.bat で呼び出す
マイナス値を返したが判定できない 負の値は符号なし整数に変換される 0以上の値のみ使用する

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

よくある質問(FAQ)

exit と exit /b の違いは何ですか?

exit はコマンドプロンプトや現在のプロセス全体を終了する命令です。exit /b は現在のバッチファイル、またはサブルーチンだけを終了して呼び出し元へ戻ります。bat内で終了コードを返したい場合は、基本的に exit /b 終了コード を使います。

exit /b 0 と exit /b 1 の違いは?

exit /b 0 は成功、exit /b 1 は失敗を表す慣習です。タスクスケジューラやCIでは、通常 0 以外の終了コードが失敗として扱われます。

ERRORLEVEL を呼び出し元で受け取るには?

別バッチやサブルーチンを call した直後に set "RC=%ERRORLEVEL%" として退避します。その後に echo や別コマンドを実行すると値が変わることがあるため、直後に保存するのが安全です。

タスクスケジューラで失敗扱いにする終了コードは?

失敗させたい場合は最後に exit /b 1 以上を返します。正常終了は exit /b 0 です。入力ファイルなし、設定ミス、通信失敗などを区別したい場合は 23 などを使い分けます。

exit /b と GOTO :EOF はどちらを使えばよいですか?

戻り値を明示したいなら exit /b 0exit /b 1 を使うのがおすすめです。GOTO :EOF は現在位置から抜けるだけで、ERRORLEVEL を明示的に変更しません。

バッチ終了後もウィンドウを残すには?

手動確認用なら末尾に pause を入れるか、cmd /k "C:\scripts\mybatch.bat" のように起動します。ただし、タスクスケジューラなどの自動実行では停止してしまうため使わないでください。

まとめ

用途 書き方 ポイント
正常終了(成功) EXIT /B 0 必ず 0 を明示。省略しない
エラー終了 EXIT /B 1(〜9) 複数理由は 2・3 と区別
ウィンドウを閉じない EXIT /B(/Bあり) EXIT(/Bなし)は cmd.exe ごと終了
戻り値の受け取り set RC=%ERRORLEVEL% CALL 直後に変数退避が安全
戻り値の条件分岐 if %RC% EQU N IF ERRORLEVEL N は「N以上」なので注意
バッチ終了後もウィンドウを残す PAUSE または cmd /k スケジューラ実行時は不要
タスクスケジューラ・CI連携 最後に必ず EXIT /B 0/1 0=成功 で結果が記録される

EXIT /B は「ウィンドウを閉じずにコードを返す」というシンプルな命令ですが、数値の有無・ERRORLEVEL の比較方法・負の値の罠・CALL の有無など、正確に使いこなすには細かい知識が必要です。今回解説したパターンを参考に、戻り値を活用した堅牢なバッチファイルを作成してください。