PHPスクリプトの多重起動を防止するには【flockによる方法】

PHPを多重起動させたくない場合

▼ 例えばこういうケース

  • あるスクリプトをCronなどで定期実行
  • その間は同一スクリプトの起動を禁止
  • 複数プロセスを存在させたくない

Cronとかでバックグラウンド処理する場合など、

多重起動されると困ることもあります。

そこでPHPスクリプトの多重起動防止策を紹介。
いくつか方法があるのでまとめてみました。

※ 間違いはコメントでご指摘ください

方法1.lockファイルを作って多重起動を回避

一時的なlockファイルを作ります。

それを目印に起動してるかを確かめられます。

もし作成済みなら起動させないというやり方です。

▼ 例 : こういうコードを書いてみた

ファイルの存在有無で多重起動を判定してるだけ

一番わかりやすいかなと思います。

この方法の欠点はCrash・エラーに対応できないこと

当然ながら以下の状況も考えられます

  • コードが何かしらのエラーをはく
  • クラッシュで強制終了する
  • Ctrl+Cなどで手動終了される

こういったケースには対応できません。

なぜなら fopen()  を使って作ったlockファイルは終了時に自動削除されません。そしてPHPにはlockファイルを必ず削除するような関数も存在しないです。

つまり unlink($lock_file);  によって明示的な削除が必要ということ。クラッシュ・予期せぬ終了をしたら一時ファイルはそのまま残ります。

だから絶対にコードがクラッシュする心配がない・予期せぬシャットダウンが起きない状況だったなら、この方法が使えるかもです。(つまり確実性に欠ける)

方法2.flockによる排他的ロックで多重起動を防ぐ

この方法ではファイルロックを使います。

具体的には排他的ロック(LOCK_EX)

これを上手く使うことで多重起動を防げます。

▼ 例 : こういうコードを書いてみた

▼ 例えば手動で1つ目のプロセスを起動

▼ 起動中に多重起動させようとすると…

このコードのflockのロックモードについて

  • LOCK_EX
    排他的なロック。このフラグ単体だけの場合、他プロセスがアクセスした時に解除されるまでブロックするという挙動になる
  • LOCK_BN
    ブロックの挙動に関するフラグ。これがセットされている場合、ブロックが発生しない(つまりロック解除を待たない)

そしてプロセスが予期せぬシャットダウン/クラッシュした場合でも対応が可能です。自動的にファイルロックが解除されるため

また LOCK_BN を付与しなかった場合、排他的ロックが解除されるまでコードが一時停止します。リソース的なこともあるので LOCK_BN は付けた方が無駄がないです

ちなみにPHPにおけるflockのOS的な互換性について

このflockはほぼ全プラットフォームで使えます

▼ 公式リファレンスの説明

flock() を使うと、(ほとんどの Unix、そして Windows さえ含む) 事実上すべてのプラットフォームで使用可能な、簡易な読み手/書き手モデルを実現できます。ロックの解放は、fclose() が実行されるか、 stream がガベージコレクションされた段階で行われます。

引用元 : https://www.php.net/manual/ja/function.flock.php

しっかりと「Windowsさえ含む」と書いてあります。

だからテスト環境に依らず汎用的に使えます。

多重起動を防止するには排他的ロックを使えばいい

むしろ他の方法とかあるんですかね?

プラットフォーム・OSに依存しない、そして確実に多重起動を防止させたいなら…今紹介したflockによる排他的ロックを利用するのが一番だと思います。

もしこれ以外の方法(ライブラリ・仕組み)を知っている方がいればコメント欄からお教えください。僕も新しい知識を知るの好きなので大歓迎です。

以上、PHPでの多重起動防止策でした。ではまた

PHP

Shareこの記事をシェアしよう!

Commentsこの記事についたコメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください