スケジュールされたタスクがバックグラウンドで定期的に実行される状況がよくありますが、タスクの実行時間が非常に長い場合は、このプログラムを手動で実行する必要がある場合もあります。繰り返し実行されやすいため、以下のクラスを開発しました。
機能: 実際のコードを実行する前に、現在と同じ動作のプロセスが実行中であり、実行中のプロセスの異常な中断が影響を及ぼさないことを確認します。
構築メソッドは pid ファイル ディレクトリの絶対パスを渡します。異なるプロセスが異なる pid ファイルに対応することを確認する必要があります。
/*
* 同じ PHP プロセスは 1 回だけ実行されます。プロセス名に基づいて、それが Linux 上でのみ実行可能であるかどうかが判断されます。
*/
クラスSyncProcess {
プライベート $pidFile;
関数 __construct($pidFile) {
$this->pidFile = $pidFile;
}
/**
* ノンブロッキングモードはプロセスが実行中かどうかを返します
*/
関数 check() {
if (PHP_OS == 'Linux') {
$pidFile = $this->pidFile;
if (!empty($pidFile)) {
$flag = false;
$pidDir = ディレクトリ名($pidFile);
If (is_dir($pidDir)) {
$flag = true;
}
If ($flag) {
$running = true;
ClearStatCache(true、$ this-> pidfile);
If (!file_exists($this->pidFile))
file_put_contents($this->pidFile, '', LOCK_EX);
$f = fopen($this->pidFile, 'r+');
If (flock($f, LOCK_EX ^ LOCK_NB)) {
$pid = トリム(fgets($f));
If (!$this->is_process_running($pid)) {
$running = false;
}
}
If (!$running) {
fseek($f, 0);
ftruncate($f, 0);
fwrite($f, getmypid());
}
群れ($f, LOCK_UN);
fclose($f);
return $running;
} その他 {
debug_print("pid ファイル($pidFile) が無効です", E_USER_WARNING);
}
} その他 {
debug_print("pid ファイルを空にすることはできません", E_USER_WARNING);
}
} その他 {
debug_print(__CLASS__ . ' Linux でのみ実行可能', E_USER_WARNING);
true を返します;
}
}
/**
* 実行中または不明なエラーが発生した場合は true を返し、実行中でない場合は false を返します
* @param 混合 $pid
*/
プライベート関数 is_process_running($pid) {
if (is_numeric($pid) && $pid > 0) {
$output = array();
$line = exec("ps -o pid --no-headers -p $pid", $output);
//戻り値にスペースが含まれています
$line = トリム($line);
if ($line == $pid) {
true を返します;
} その他 {
If (空($output)) {
false を返す;
} その他 {
If (php_sapi_name() == 'cli')
$n = "n";
その他
$n = "
";
// ここまで来たら、何か問題があるはずです
$output = implode($n, $output);
debug_print($output, E_USER_WARNING);
true を返します;
}
}
}その他{
false を返します;
}
}
}
デモ: