PHPを使用したcronjobシステムがあります。cron.phpという名前のファイルがあり、ロードされていないかどうかを確認したいので、ロードします。このファイルが1回だけ実行されることは私にとって非常に重要であり、定義がすでに実行されている方法が必要です。exec、systemなどのシステム関数を使用できません...解決策はありますか?
注:スクリプトをCURLで実行しましたが、この場合、include_oneとrequire_onceは機能しません。
PHPを使用したcronjobシステムがあります。cron.phpという名前のファイルがあり、ロードされていないかどうかを確認したいので、ロードします。このファイルが1回だけ実行されることは私にとって非常に重要であり、定義がすでに実行されている方法が必要です。exec、systemなどのシステム関数を使用できません...解決策はありますか?
注:スクリプトをCURLで実行しましたが、この場合、include_oneとrequire_onceは機能しません。
flock()
次のように、phpファイル自体をロックするために使用できます。
<?php
class Lock{
private $fp;
function __construct(){
$this->fp=fopen(__FILE__,'r');
if (!flock($this->fp,LOCK_EX|LOCK_NB)) {
die('already running !'.PHP_EOL);
}
}
function __destruct(){
flock($this->fp,LOCK_UN);
fclose($this->fp);
}
}
$lock=new Lock();
// simulate some processing
sleep(60);
echo "END";
?>
require_onceまたはinclude_onceを使用できますか?
require_once
ファイルを評価できない場合、PHPの致命的なエラーがスローされます(実行が停止します)。
include_once
PHP警告をスローします(実行が続行される場合があります)。
// Require tasks.php to run once
require_once 'path/to/tasks.php';
// Attempt to run tasks.php and only once
include_once 'path/to/tasks.php';
私があなたを正しく理解しているなら、あなたはあなたのcron.phpスクリプトがcronによって二度と開始されないようにしたいのですが、それは別のPHPスクリプトから呼び出されていませんか?(その場合、require_onceが正しい答えになります)
私が理解しているように、スクリプトが実行中であることを示すマーカーを保存し、スクリプトの最後でそのマーカーを削除する必要があります。
環境に応じて、小さなファイルを作成するか.lock
、データベースにステータス=ロックされたエントリを保存することができます。
編集:これはfileメソッドを使用した小さなコード例です:
<?php
// cron.php
$path = '/path/to/your/data/directory/';
if (file_exists($path . '.lock') {
die('cron.php is already running');
}
// if script reaches this point, it is not locked -> create a lock
file_put_contents($path . '.lock', 'lockfile created at ' . now());
//... your code....
//unlocking
unlink($path . '.lock');
?>
cURLを使用している場合は、cURLを使用してなどのページをリクエストしていると思いますhttp://domain.com/cron.php
。cURL / wget / browser / etcを介してスクリプトを要求しているマシンには、スクリプトがサーバー上ですでに実行されているかどうかを知る方法がありません。cron.php
ただし、スクリプトを1回だけ実行するように構成できます。
<?php
// attempt to obtain a lock
$fp = fopen(basename(__FILE__) . ".lock", "w");
if (flock($fp, LOCK_EX | LOCK_NB) === false) {
echo basename(__FILE__) . ": already running\n";
exit(-1);
}
// code goes here
echo date("Y-m-d H:i:s") . ": cron job started\n";
sleep(30);
echo date("Y-m-d H:i:s") . ": cron job ended\n";
// release the lock
flock($fp, LOCK_UN);
fclose($fp);
サンプルコードはPHPflock
関数を使用しています。このLOCK_EX
フラグは、PHPに排他ロックを取得する必要があることを通知します。つまり、他のプロセスがファイルにアクセスすることは許可されていません。はPHPに、ブロックして(ロックが解放されるのを待って)すぐLOCK_NB
に戻るべきではないことを通知します。false
一緒に、2つのスイッチは、最初のプロセスがファイルをロックしている間、2番目のプロセスがファイルをロックできないことを保証します。
include_once('class.php');
php.netの状態
include_onceステートメントは、スクリプトの実行中に指定されたファイルをインクルードして評価します。これはincludeステートメントと同様の動作ですが、唯一の違いは、ファイルのコードがすでにインクルードされている場合、再びインクルードされないことです。名前が示すように、それは一度だけ含まれます。
あなたが使用することができますrequire_once
またはinclude_once
includeステートメントとrequireステートメントの両方の一般的な構文は次のとおりです。
include "file_to_load.php";
include_once "file_to_load.php";
ステートメントを使用する場合include_once/require_once
、ファイルを複数回ロードまたは実行することはできません。これらの2つの方法のいずれかを使用してファイルを2回ロードしようとすると、そのファイルは無視されます。スクリプト内で同じ関数を複数回定義することは許可されていないため、これらの関数を使用すると、開発者は、スクリプトが以前にロードされているかどうかを確認しなくても、必要に応じてスクリプトを含めることができます。
注外部include_once
ファイルから値を返す機能は、ステートメントのみに制限されています。ステートメントはこのrequire_once
方法では使用できません。
require_onceまたはinclude_onceのいずれかを使用できます。
何を使用するか混乱している場合、この2つの違いは次のとおりです。
require_onceは先行するコードの実行を停止し、致命的なエラーが発生します。言及されたファイルが見つからない場合、先行するコードを続行する場合は、ファイルが見つからなくても使用しないでください。
ここで、include_onceは先行するコードの実行を継続します。
この場合、データベースを使用して、データベースと2番目の列にページのエントリを作成し、ロードされているかどうかを確認できます(たとえば'0'
、まだロードされておらず、ロードされている場合'1'
)。ページがロードされたときにその行の値を最初に保持し、その列をとして'0'
更新します'1'
。