2012-05-08 18 views
1

私はPHPでcronjobシステムを持っています。私はcron.phpという名前のファイルを持っていて、ロードされていないかどうかをチェックしたいのですが、ロードしてください。このファイルが1回だけ実行されることは非常に重要であり、すでに定義されている定義方法が必要です。私はexec、systemのようなシステム関数を使うことはできません...あなたはどんな解決策もありますか?PHPスクリプトが一度読み込まれることを確認する方法

注:私はスクリプトのCURLを実行しますが、include_oneとrequire_onceはこのケースでは機能しません。

+2

既存のcron.phpがすでに実行されている場合、cronジョブcron.phpが実行されないようにしたいのですか? (これは現在の回答とは異なるので、明らかにする必要があります) – Ben

+0

私の答えを見て、どこか遅れているかどうか教えてください –

+1

あなたのスクリプトの最後の実行時間をどこかに保存する必要がありますデータベース、テキストファイル)。最後の実行時間/日付(userIDなど)を確認し、何らかの条件(タイムアウト)が与えられた場合にのみスクリプトを実行します。 – djot

答えて

7

あなたはこのように、PHPファイル自体をロックするflock()を使用することができます。

<?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"; 
?> 
+0

Apacheサーバーが再起動するとLOCKが期限切れになったのですか? – IVIR3zaM

+1

@ IVIR3zaM:スクリプトが強制終了されると、ロックも失効します。 (もしApacheが再起動すると、apacheがスクリプトをkillするかどうかはわかりませんが、私はそう考えています) – stewe

+1

right、flockを忘れました。いくつかの議論がありましたが、信頼性の高い群が異なるサーバー構成でどのくらい信頼できるのですか。 - 私もあまりにも正常に起動したときにスクリプトを実行すると思う – cypherabe

2

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'; 
1

あなたはrequire_onceまたはinclude_once

に含まとステートメントを必要とし、両方の一般的な構文を使用することができます次のとおりです。include_once/require_once文が使用されている場合は

include "file_to_load.php"; 
include_once "file_to_load.php"; 

、ファイルがロードできませんまたは複数回実行されます。これら2つの方法のいずれかを使用してファイルを2回ロードしようとすると、そのファイルは無視されます。スクリプト内で同じ関数を複数回定義することは容認できないため、開発者はこれらの関数を使用して、以前にロードされたかどうかを確認することなく必要に応じてスクリプトを含めることができます。

外部ファイルから値を返す機能は、include_onceステートメントのみに制限されています。 require_onceステートメントは、この方法では使用できません。

+0

それは間違っています。私はCURLスクリプトを実行します。 include_oneはクライアントごとであり、スクリプトはすべてのクライアントに対して1回実行したいと考えています – IVIR3zaM

1
include_once('class.php'); 

php.net状態

のinclude_once文は、スクリプトの実行時に指定したファイル を評価します。これは、 includeステートメントと同様の動作ですが、ファイルのコード が既に含まれている場合は、再度インクルードされません。 名前のとおり、1度だけ含まれます。

0

require_onceまたはinclude_onceのいずれかを使用できます。

あなたは、この両者の違いは、あなたも、ファイルを継続するためのコードの前にしたい場合は、ファイルに述べたがそのように が見つからない場合

のrequire_onceは、上記のコードの実行を停止し、trwos致命的なエラーになるということであるものを使用するために混同されている場合見つからない場合は使用しないでください。

ここで、include_onceは前のコードの実行を継続します。

2

あなたの問題は

を「PHPスクリプトが実行されているかどうかをチェックし、」私が正しくあなたを理解し、あなたのcron.phpないようにしたい場合は、この

Check if a php script is still running

+0

スクリプトはうまくいきませんが、スクリプトでは多くの作業が実行され、時間がかかり過ぎることがあります。実行されていないし、再度実行する – IVIR3zaM

2

を参照してくださいと本質的に同等ですスクリプトはもう2回、cronで始めるのではなく、別のPHPスクリプトから呼び出されませんか? (その場合、require_onceは正しい答えになります)

私が理解しているように、スクリプトが実行されていることを示すマーカーを保存し、スクリプトの最後にそのマーカーを削除する必要があります。

環境によっては、小さなファイル(.lock)を作成するか、ステータス=ロックされたエントリをデータベースに保存することができます。

編集:ここでのファイル方式を使用して、小さなコードの例です:

<?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'); 
?> 
+0

はい、あなたはそれを理解しています。それはトラフCURLと呼ばれた。あなたのアイデアは問題を抱えているかもしれません。おそらく、Apacheが再起動し、スクリプトのリンクが解除されていない可能性があります。ロックファイルと私のシステムが永遠にシャットダウン – IVIR3zaM

+0

友人のアドバイスでflock()を使用して解決しました – IVIR3zaM

0

あなたがのためにデータベースを使用することができますこの場合は、データベースにページのエントリを作成し、ロードされているかどうかを確認するために2番目の列を指定します(たとえば、ロードされていない場合は'0'、ロードされていない場合は'1')。最初にその行の値を'0'とし、ページがロードされるとその列を'1'として更新します。

2

あなたがcURLを使用している場合、私はあなたがhttp://domain.com/cron.phpのようなページを要求するためにcURLを使用していると考えています。 cURL/wget/browser/etcを介してスクリプトを要求しているマシンは、スクリプトがすでにサーバ上で実行されているかどうかを知る方法がありません。しかし、あなたは一度だけ実行するようにあなたのcron.phpスクリプトを設定することができます。

<?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); 

サンプルコードはPHP flock機能を使用しています。 LOCK_EXフラグは、排他的ロックを取得する必要があることをPHPに通知します。すなわち、ファイルにアクセスする他のプロセスは許可されない。 LOCK_NBは、ブロックするべきではない(ロックが解放されるのを待つ)ことをPHPに指示し、すぐにfalseを返します。一緒に、2つのスイッチは、第1のプロセスがロックしている間に、第2のプロセスがファイルをロックできないことを保証する。

+0

ありがとう、私は一つの質問。 Apacheサーバーがこのロックを再起動すると、削除されたかどうか – IVIR3zaM

+0

私はそれをテストし、それについてもっと読む、はい、すべてのロックが解除されたapacheが再起動される。ありがとう – IVIR3zaM

+1

@ IVIR3zaM:私は窓にApacheを持っています。 PHPプロセスが完了するのを待っているようです。 Apache(またはPHPプロセス)が_killedの場合はどうなるかわかりません。私はスクリプトを殺したときに正しくロックを解除したPHP CLIのスクリプトをテストしました。あるいは、CTRL + Cを使って終了しました。 PHPのドキュメントでは、ロックは必須ではありませんが、ロック機構はkill-safeであることを示している可能性があります。 –

関連する問題