BATファイルで、ロックファイルを使った排他制御を行う
これは、コマンドプロンプト(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
@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
@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つの処理の排他制御を完全に同じ形にするとかち合う可能性があるように思うので、上記でやったように、優先度をつけて微妙に異なる実装にする方が気が楽です。