時々(あるいはしょっちゅう)あるのですが、バッチファイルが「二重に動くと吾妻しくねぇなぁ」な状況があります。
よくロックファイルによる二重起動防止とかを見るのですが…もうちょっと楽な手段があるので、まぁ「カードの一枚」程度に。
機構としては、至極一般的な「セマフォ」を使います。
セマフォは「プロセス間通信」の一環になります。…それ以上を知りたかったら、C言語系の書籍を適宜あたってくださいませ。
…そのうち解説するかもしんまい。リクエストはコメントもしくはリアルで直接どんぞ。
サンプルコードから、早速かつとっとと実装をまなんでみませう。
まずは「ロックされていない」状態を体感して確認。
バッチファイルはこんな感じ。ファイル名は「t.php」という、素晴らしく投げたネーミング。
// 処理 $pid = posix_getpid(); // print "start({$pid}) \n"; sleep(5); print "end({$pid}) \n";
わかりやすい感じでひとつ。startってデバッグ出力してから、sleep5がきっと「色々なバッチ処理」。endもデバッグ出力的な感じ?
…あ、sleep5秒は、短いようで微妙に長いんで。いらいらしたら、適当に数字を入れ替えてください。
この子をあえて「ほぼ同時に」叩きます。
こんなファイルを用意。テストなんで、おいちゃんはこのファイル名を「ttt」としました。
php t.php & php t.php & php t.php & php t.php & php t.php &
これを実行してみます。
sh ttt
[gallu:~]start(10228)
start(10231)
start(10227)
start(10229)
start(10230)
end(10228)
end(10227)
end(10231)
end(10229)
end(10230)
排他制御もへったくれもありません。
では、セマフォで排他してみましょう。
// セマフォを取得 $sobj = sem_get(123); $r = sem_acquire($sobj); // 処理 $pid = posix_getpid(); // print "start({$pid}) \n"; sleep(5); print "end({$pid}) \n"; // セマフォを解放 sem_release($sobj);
たった三行で、ほらこのとおり。
sh ttt
[gallu:~]start(10353)
end(10353)
start(10351)
end(10351)
start(10352)
end(10352)
start(10355)
end(10355)
start(10354)
end(10354)
OSの「微妙なプロセスIDのふりかた」は気にせずに。
ちなみに、丁寧に sem_release してますが、基本、上述のコードなら不要です。
// セマフォを取得 $sobj = sem_get(123); $r = sem_acquire($sobj); // 処理 $pid = posix_getpid(); // print "start({$pid}) \n"; sleep(5); print "end({$pid}) \n";
実行結果
sh ttt
start(10515)
[gallu:~]end(10515)
start(10517)
end(10517)
start(10516)
end(10516)
start(10518)
end(10518)
start(10519)
end(10519)
こんな感じ。
昨日、勉強会っていうかぶっちゃけ「開発合宿もどき」で、うちの子たちが知らんかったので、備忘録かねて。