2016-12-15 9 views
1

特定のPHPスクリプト(Webリクエストによって開始される)が同時に複数回実行されないようにする必要があります。信頼できるPHPスクリプトリエントラントロック

バイナリでは、特定のバイナリのプロセスが既に存在するかどうかを確認するのは簡単です。

しかし、PHPスクリプトはいくつかの経路で実行することができます。 CGI、FCGI、Webサーバーモジュール内などで、システムコマンドを使用して見つけることができません。

特定のスクリプトの別のインスタンスが現在実行されているかどうかを確実に確認する方法はありますか?

+1

フラグを設定する:ファイルを作成する、データベースにフラグを保存する、またはRedisまたはmemcachedキーを使用する。最終的に有効期限が切れるように設定するか、最初のスクリプトが終了した場合は手動でクリーンアップするようにしてください。 –

+0

スクリプトが長時間実行されても信頼できる「期限切れ」を実装するのは難しいです。それが失敗した場合、我々はそれが死んだことを確かめるために未知の時間を待つ必要があるだろう。 – dronus

+1

これはXY問題である可能性が非常に高い。 PHPスクリプトが一度だけ実行されていることを確認するには、どのような理由でこのチェックが必要ですか?私は、おそらく、この認識された解決策を伴わない実際の問題に対するより良いアプローチがあるため、尋ねています。 – Mjh

答えて

4

1は、ローカルアプリケーションで選んだだろうとまったく同じ戦略が使用されます。

プロセスは、「ロックファイル」を管理。

ファイルシステムで静的ロケーションを定義します。スクリプトの起動時に、その場所にロックファイルが存在するかどうかを確認します。最初にそのロックファイルを作成していなければ、次に進みます。スクリプトの解凍中に、そのロックファイルを再度削除します。そのようなロックファイルは単純な受動的なファイルであり、その存在は興味があり、しばしばその内容ではありません。これは標準的な手順です。

ロックファイルをパッシブセマフォとして使用するだけでなく、生成プロセスのプロセスIDを保存すると、余分なキャンディーポイントを獲得できます。これにより、その後のプロセスの検証が実際にはまだ行われているか、平均してクラッシュしてしまいます。このようなクラッシュは古いロックファイルを残し、デッドロックを引き起こすので意味があります。正しくの一部では、PHPスクリプトを単独でウェン環境プロセスIDに使用されているシナリオが確実かどうかをテストするために十分ではないかもしれないと述べているコメントで述べた問題を回避するには


は、ではなく、が直接PHPスクリプト自体を実行するタスクにトリガーしますが、単なるラッパースクリプトです。そのラッパーは実行される実際のタスクをHTTPサーバーにサブ要求に委任しながらロックファイルを管理します。これにより、制御ラッパー・スクリプトは要求状態の追加情報を使用できます。 PHPスクリプトを実行している実際のタスクが実際に予告なしにクラッシュした場合、要求しているラッパーはそのことを知っています:各要求は、実行中のタスクが正常に終了したかどうかを判断できる特定のHTTPステータスコードで終了します。その設定は、ほとんどの目的にとって十分に信頼できるものでなければなりません。簡単なラッパースクリプトのクラッシュまたは終了の可能性は、確実に処理できるロック戦略がないシステム障害の領域に入ります。

+0

偉大で正確な答え、私はちょうどあなたのポイントを示すいくつかのコードを提供することができればそれを愛するだろう:) – Mjh

+1

PHPが実行される方法に応じてPIDがないので、ファイル内のPIDを格納する機能しません。 PIDがどこにあるのかは、すでに述べたようにプロセスの実行をチェックするだけです。 PHPスクリプトはいくつかの理由(ユーザーの中止、メモリ不足、Webサーバーの再起動)で実行を停止する可能性があり、コードのファイナライズを確実に行う方法がないため、2回だけの通信(開始と終了)は非常にエラーが発生しやすくなります。 – dronus

+0

したがって、ロックファイルを使用すると、スクリプトが実行されている間にそのロックファイルを更新することになります。手作業の協調マルチタスキングのような特殊な手順です。 – dronus

0

PHPが常にファイルロックの信頼できる方法を提供するとは限りません(CGI、FCGI、サーバーモジュール、および設定などのスクリプトの実行方法によって異なります)。

PHPスクリプトは、たとえば、そのCLIの変形で別のPHPインタプリタを呼び出すことができます。これは、ロックを確認できるユニークなPIDを提供します。 PIDは、PIDを使用しているプロセスが依然として存在するかどうかを問い合わせることによって、失効したロックをチェックできる、いくつかのロックファイルに格納する必要があります。

多分、シェルスクリプト内でロックを必要とするすべてのタスクを実行することもできます。シェルスクリプトは一意のPIDも提供し、終了後に信頼できるリリースを行います。シェルスクリプトは、実行中であるかどうかを確認するために使用できる一意のファイル名を使用することもできます。

セマフォ(http://php.net/manual/de/book.sem.php)も使用できます。これは、PHPインタプリタによって明示的に管理され、スクリプトの有効期間を反映します。彼らはかなりうまくいくように見えますが、早すぎるスクリプトが死んだ場合の信頼性についてはあまり気にしません。

また、PHPスクリプトによって起動された外部プロセスは、スクリプトが終了しても実行を継続できることに注意してください。たとえば、ユーザーがFCGIをアボートすると、クライアントの接続が切断されたにもかかわらず動作する、passthruプロセスが解放されます。十分な出力が蓄積されているか、全く蓄積されていないと、後で殺されることがあります。 そのような外部プロセスもロックする必要があります。これは、PHPが獲得したセマフォだけでは実行できません。

関連する問題