これは、コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiitaの20日目の記事です。19日目は @nmrmsys さんの “Tee for ToeKick 実行コマンドラインまで含めてログファイルに出力するコマンド” でした。
残りは全部自分です。最後まで駆け抜けるよ!※Windows 10 Home 64bit 搭載のcmd.exeにて検証を行っています。

さてさて

今回はBATファイルにおける排他制御に関して書きますが、自分がやったことのある内容で、ということで、もうちょい範囲を限定します。
今回は**「2つのBATファイルの実行について、ロックファイルを使った排他制御を行う」**という内容で書きます。

挙動について

「処理1.BAT」と「処理2.BAT」の実行を排他制御します。

  • 「処理1.BAT」が起動した直後に「処理2.BAT」が起動すると「処理2.BAT」は待ち状態になり、「処理1.BAT」が終了すると「処理2.BAT」が動き出す
  • 「処理2.BAT」が起動した直後に「処理1.BAT」が起動すると「処理1.BAT」は待ち状態になり、「処理2.BAT」が終了すると「処理1.BAT」が動き出す
  • 「処理1.BAT」と「処理2.BAT」が同時に起動した場合、**「処理1.BAT」が優先される**

書きました

※検証しやすいように両方共最後にpauseを入れていますがお気になさらず

処理1.BAT
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@echo off

set LOCK_PREFIX=lock
set LOCK_FILE=%LOCK_PREFIX%.proc1

rem チェック前にロックファイルを作成する
copy nul > %LOCK_FILE%

:CHECK
echo ロックファイルのチェック(%~n0)

rem 自分のロックファイルのみの場合、ERRORLEVEL=1
rem 他人のロックファイルが存在する場合、ERRORLEVEL=0
dir /b %LOCK_PREFIX%.* | findstr -v %LOCK_FILE% > nul
if %errorlevel%==0 timeout /t 2 > nul & goto :CHECK

:MAIN
echo 時間のかかる何らかの処理 開始
timeout /t 5 > nul
echo 時間のかかる何らかの処理 終了
echo.

:END
del %LOCK_FILE%

pause

処理2.BAT
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@echo off

set LOCK_PREFIX=lock
set LOCK_FILE=%LOCK_PREFIX%.proc2

:CHECK
echo ロックファイルのチェック(%~n0)

rem 誰かのロックファイルが存在する場合、ERRORLEVEL=1
dir /b %LOCK_PREFIX%.* > nul 2>&1
if %errorlevel%==0 timeout /t 2 > nul & goto :CHECK

rem チェック後にロックファイルを作成する
copy nul > %LOCK_FILE%

:MAIN
echo 時間のかかる何らかの処理 開始
timeout /t 5 > nul
echo 時間のかかる何らかの処理 終了
echo.

:END
del %LOCK_FILE%

pause


簡単ですが、こんな感じで。私見ですが、2つの処理の排他制御を完全に同じ形にするとかち合う可能性があるように思うので、上記でやったように、優先度をつけて微妙に異なる実装にする方が気が楽です。