batで処理結果を呼び出し元へ返すなら、基本は exit /b 終了コード です。exit だけを書くとコマンドプロンプトごと閉じることがありますが、exit /b は現在のバッチやサブルーチンだけを終了し、ERRORLEVEL に成功・失敗の番号を残せます。
この記事では exit /b 0 と exit /b 1 の違い、ERRORLEVEL の受け取り方、タスクスケジューラで失敗扱いにする終了コード、GOTO :EOF との使い分けまで、実務で迷いやすいポイントを整理します。
EXITとEXIT /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
目的別ショートカット
| 目的 | 読む場所 | 主なキーワード |
|---|---|---|
exit と exit /b の違いを知りたい |
EXIT /B とは? /B オプションの意味 | ウィンドウを閉じない、呼び出し元へ戻る |
| 正しい構文だけ先に確認したい | EXIT /B の構文 | exit /b [終了コード] |
exit /b 0 と exit /b 1 を使い分けたい |
EXIT /B 0 と EXIT /B 1 の意味 | 0=成功、1以上=失敗 |
ERRORLEVEL を受け取りたい |
ERRORLEVEL で戻り値を受け取る | call、set 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 にセット |
EXIT /B(数値なし)は直前コマンドの ERRORLEVEL をそのまま返します。意図せずエラーコードを伝播させたくない場合は 必ず
EXIT /B 0 や EXIT /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 1 は「ERRORLEVEL が 1 以上」を意味します。EQU 1(ちょうど1)ではありません。複数コードを区別する場合は 大きい値から順に判定するか、
%ERRORLEVEL% EQU N 形式を使ってください。
方法3:ERRORLEVEL を変数に退避してから比較(最安全)
CALL の直後に別コマンドを挟むと 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 したときも同様に戻り値を受け取れます。
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以上の値のみ使用する |
あわせて確認したい関連記事
- バッチファイル(bat)の目的別記事一覧
- エラー時に処理を中断・終了する方法
- ファイル存在チェックの書き方
- schtasksコマンドでタスクスケジューラを制御する方法
- バッチファイルで実行ログを出力する方法
よくある質問(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 です。入力ファイルなし、設定ミス、通信失敗などを区別したい場合は 2 や 3 などを使い分けます。
exit /b と GOTO :EOF はどちらを使えばよいですか?
戻り値を明示したいなら exit /b 0 や exit /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 の有無など、正確に使いこなすには細かい知識が必要です。今回解説したパターンを参考に、戻り値を活用した堅牢なバッチファイルを作成してください。

