3

シェル コマンドを使用して、このプロセスが現在実行されているかどうかを判断する PHP コードを見たことがありますが、紛失してしまいました。これを行う方法のヒントを教えてください。

アイデアは、php ファイルを作成し、このファイルをphp -fを使用して cron ジョブとして実行することです。スクリプトの実行時間は 10 秒かもしれませんが、10 分かもしれません。このcronを毎分1回実行する必要があり、前の分のcronがまだ実行されている場合は、新しいcronを停止して他のcronを終了させます。

私はシェルプログラミングがあまり得意ではないので、助けが必要です。

PS アイデアは、バックグラウンドで無限のPHPプロセスを配置せずにデーモンを作成することです。

4

3 に答える 3

3

ロック ファイルに対して排他的非ブロッキング ロックを取得するようにしてください。成功した場合、プロセスは実行中の唯一のインスタンスであり、終了するまでロックを保持する必要があります。ロックの取得に失敗した場合は、実行中の別のインスタンスが既に存在するため、終了する必要があります。

于 2012-05-28T11:48:13.123 に答える
2

多くの目的で、次のコードは問題ありません(競合状態が発生する可能性がありますが、詳細なcronジョブの場合、これはおそらく非常にまれです)。

if (file_exists($lockfilename)) {
   ... // lock is already taken
} else {
   if ( !file_put_contents($lockfilename, $lockstring)) {
      error("unable to write $lockfilename");
   }
   $lock_taken = true;
   ... // do what you have to do
   if ( !unlink($lockfilename)) {
      warning("unable to unlink $lockfilename");
   }
   $lock_taken = false;
}

グローバル変数$lock_takenは、実行が停止するたびにロックファイルが確実に削除されるようにするために役立つ場合があります。$lockstring日付またはUnixタイムスタンプである可能性があります。これは、明らかに古すぎる場合にロックを削除するのに役立つ場合があります(ただし、十分filemtime()な場合もあります)。

競合状態を絶対に危険にさらすことができない場合は、次のようなことを行う必要があります

if ( !($lockfile = fopen($lockfilename, "x"))) {
   ... // lock is already taken
} else {
   $lock_taken = true;
   ... // write something to lockfile (optional)
   fclose($lockfile);
   ... // do what you have to do
   if ( !unlink($lockfilename)) {
      warning("unable to unlink $lockfilename");
   }
   $lock_taken = false;
}

ただし、これはローカルロックファイルに対してのみ機能します。

于 2012-05-28T12:30:50.617 に答える
2

ファイルを削除する前にスクリプトがクラッシュした場合、ロックは引き続き有効であるため、排他的なファイル ロック アプローチは「ファイルが存在するかどうかを確認する」アプローチよりも優れています。

ファイルロックのコードは次のとおりです。

//Allow only one instance
$fileHandler = fopen('file_lock.lock', 'w');
$hasLock = flock($fileHandler, LOCK_EX | LOCK_NB);
if (!$hasLock)
    die("Another instance is already running");

//do work

//release lock
flock($fileHandler, LOCK_UN);
fclose($fileHandler);

スクリプトの実行後にシステムが自動的にロックを解除するため、ロック解除ブロックはオプションです。

于 2013-04-07T05:39:49.737 に答える