概要
Windowsのbatchではtrap
のようなコマンドや、set -e
のようなエラーで即終了するような機構がないためエラーハンドリングする場合は%ERRORLEVEL%
を全コマンド実行後にチェックする必要がある。
しかし、それだとエラーチェックの行が多くなりすぎるため読みづらいコードになってしまう。
その点を改善できる方法を考えてみる。
単純にエラーコードを返す
結論から言うと、以下のようにすることでエラーコードを呼び出し側に返すことができる。
some_command || exit /b !ERRORLEVEL!
これはサブルーチンのcall
に対しても使えるため、
call :sub || exit /b !ERRORLEVEL!
exit /b
:sub
some_commandA || exit /b !ERRORLEVEL!
some_commandB || exit /b !ERRORLEVEL!
some_commandC || exit /b !ERRORLEVEL!
exit /b
のように使うことができる。
エラー表示をする
batchにする以上何度も実行されると思うが、呼び出しをする度にコマンドプロンプトなどで%ERRORLEVEL%を確認するのは不毛なのでエラー表示もbatchにしたい。
some_command || call :onerror || exit /b !ERRORLEVEL!
exit /b
:onerror
echo エラー発生[%ERRORLEVEL%]
exit /b
上記の処理を見るとわかる通りcall
やecho
では%ERRORLEVEL%
の書き換えが起こらないのでエラーハンドラをcall
すれば問題なく処理できる。
ちゃんと引数として渡したい場合はcall :onerror "%ERRORLEVEL%"
としてあげれば大丈夫だった。
:onerror
内での処理の内容によっては%ERRORLEVEL%
が書き換わる可能性があるため、:onerror
の先頭で変数に格納するのが安全かもしれない。
batchファイルとして私が思う完成系
最後に私の思うbatchファイルの完成系テンプレートを置いておくことにする。
@echo off
@setlocal
call :entrypoint || call :onerror
exit /b
:onerror
echo Error[%ERRORLEVEL%]
exit /b
:entrypoint
some_commandA || exit /b !ERRORLEVEL!
some_commandB || exit /b !ERRORLEVEL!
some_commandC || exit /b !ERRORLEVEL!
exit /b