PHP 프로 세 스 동기 화 코드 인 스 턴 스

이러한 상황 이 자주 발생 합 니 다.계획 임 무 는 정 해진 시간 에 백 스테이지 에서 특정한 phop 프로그램 을 수행 하고 가끔 은 수 동 으로 실행 해 야 합 니 다.여러 사람 이 이 프로그램 을 수행 해 야 할 수도 있 습 니 다.만약 에 임무 가 오래 지속 되면 중복 집행 이 발생 하기 쉬 우 므 로 다음 과 같은 종 류 를 개 발 했 습 니 다.
역할:실제 코드 가 실행 되 기 전에 현재 와 같은 작업 을 하 는 프로 세 스 가 실행 되 고 있 는 지 확인 하 십시오.높 은 병행 실행 은 신뢰 할 수 있 습 니 다.실행 중인 프로 세 스 가 중간 에 이상 하 게 중단 되 는 것 은 영향 을 주지 않 습 니 다.
구조 방법 은 pid 파일 디 렉 터 리 의 절대 경 로 를 전달 하고 서로 다른 프로 세 스 가 서로 다른 pid 파일 에 대응 하도록 스스로 보증 해 야 합 니 다.

<?php

/*
 * PHP , , linux, 。
 */

class SyncProcess {

 private $pidFile;

 function __construct($pidFile) {
  $this->pidFile = $pidFile;
 }

 /**
  *
  */
 function check() {
  if (PHP_OS == 'Linux') {
   $pidFile = $this->pidFile;
   if (!empty($pidFile)) {
    $flag = false;
    $pidDir = dirname($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 = trim(fgets($f));
      if (!$this->is_process_running($pid)) {
       $running = false;
      }
     }
     if (!$running) {
      fseek($f, 0);
      ftruncate($f, 0);
      fwrite($f, getmypid());
     }
     flock($f, LOCK_UN);
     fclose($f);
     return $running;
    } else {
     debug_print("pid file($pidFile) is invalid", E_USER_WARNING);
    }
   } else {
    debug_print("pid file cant't be empty", E_USER_WARNING);
   }
  } else {
   debug_print(__CLASS__ . ' can only run in Linux', E_USER_WARNING);
   return true;
  }
 }

 /**
  * true, false
  * @param mixed $pid
  */
 private function is_process_running($pid) {
  if (is_numeric($pid) && $pid > 0) {
   $output = array();
   $line = exec("ps -o pid --no-headers -p $pid", $output);
   //
   $line = trim($line);
   if ($line == $pid) {
    return true;
   } else {
    if (empty($output)) {
     return false;
    } else {
     if (php_sapi_name() == 'cli')
      $n = "
";
     else
      $n = "<br>";
     //
     $output = implode($n, $output);
     debug_print($output, E_USER_WARNING);
     return true;
    }
   }
  }else {
   return false;
  }
 }

}

Demo:

$sync = new SyncProcess(APP_PATH . '/data/pid'.implode('', $this->getRoute()));
if ($sync->check()) {
 exit("process is running
");
}

좋은 웹페이지 즐겨찾기