HIDARI日記(右)

そのときどき興味ある技術を中心にだらだら書いてます。内容は個人の見解であり、所属する企業を代表するものではありません。

コマンドプロンプトの errorlevel を確認してエラーなら処理を終了する方法

基本中の基本なんですが、最近はエラーが起こったら処理を終了することが重要になってくるとき、例えば「コマンドプロンプトしか使えない状況でCI回したい」みたいな縛りプレイしてるときに使ってます。具体的にはJenkinsのジョブを失敗させるためですが。

手順

まず、バッチファイルに以下の様なサブルーチンを用意しておきます。

:SuccessOrDie
if not %errorlevel% == 0 (
    echo [ERROR] :P
    exit 1
)
exit /b 0

これをerrorlevelに戻り値を返すコマンドのあとにcallで呼び出します。

xcopy src\hoge.dll dest\ /Y /F
call :SuccessOrDie

もしエラーが発生していたら(errorlevel0でなかったら)exit 1が実行されコマンドプロンプトが戻り値1、つまりエラーで終了します。Jenkinsだとこれだけでジョブを失敗させることができます。

一方、エラーがなかった場合(errorlevel0の場合)はexit /b 0が実行されます。/bオプションによってサブルーチンを終了し呼び出し元に戻ることができます。

バッチファイルではよくgoto使ってエラー処理をしているのを見かけますが、呼び出し元に戻りたいのに加えて、思わぬバグが生まれることがあるので使うのを避けて、callexitの組み合わせを使っています。

errorlevelを含む条件式での注意点

if not errorlevel 0 exit 1

って書いてしまうと「0以上ではないとき終了する」になるので、errorlevelが負のときにしかexitが実行されません。

if not %errorlevel% == 0 exit 1

というように展開した上で文字列での比較を行うことで「0ではないとき終了」するようになります。

手動で実行したい!

基本的にはCIサーバでコンソール出力を記録しながら使うことを前提としたバッチファイルですが、CIとかよくわからんから手動でもログを残して実行できるようにしておいてくれないと困るって言う人が稀によくいます。

そういうときは以下のような処理を書いた手動実行用のラッパーを用意しています。

@echo build.batを実行します。
@echo ログは build.bat.logに出力されます。
@pause

@echo 実行中...
@call build.bat > build.bat.log 2>&1

このバッチファイルをダブルクリックするだけでログ出力まで行います。

サンプル全文

ここまでで紹介したあれこれをまとめたサンプルの全文です。

@echo off
set SELF_PATH=%~dp0
cd /d %SELF_PATH%

xcopy src\hode.dll dest\ /Y /F
call :SuccessOrDie

goto end

:SuccessOrDie
if not %errorlevel% == 0 (
    echo [ERROR] :P
    cd /d %SELF_PATH%
    exit 1
)
exit /b 0

:end
echo [SUCCESS] :)
echo on
exit 0