PHP进程同步代码实例
经常遇到这样一种情况,计划任务定时后台执行某个php程序,有时候也需要手动执行,可能多个人都需要执行这个程序,如果任务持续时间非常长,就很容易造成重复执行,所以就开发了下面的类。
作用:在实际代码运行前检查与当前相同操作的进程是否正在运行,高并发运行是可靠的,运行中的进程中途异常中断不会产生任何影响。
构造方法传递pid文件目录的绝对路径,需要自己保证不同进程对应不同pid文件。
<?php
/* *同一个PHP进程只运行一次,根据进程名字判断是否为排重进程,只能运行于linux,高并发条件下是并发安全的。 */
classSyncProcess{
private$pidFile;
function__construct($pidFile){ $this->pidFile=$pidFile; }
/** *非阻塞方式返回进程是否正在运行 */ functioncheck(){ 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("pidfile($pidFile)isinvalid",E_USER_WARNING); } }else{ debug_print("pidfilecant'tbeempty",E_USER_WARNING); } }else{ debug_print(__CLASS__.'canonlyruninLinux',E_USER_WARNING); returntrue; } }
/** *如果正在运行或者发生未知错误返回true,如果没有运行返回false *@parammixed$pid */ privatefunctionis_process_running($pid){ if(is_numeric($pid)&&$pid>0){ $output=array(); $line=exec("ps-opid--no-headers-p$pid",$output); //返回值有空格 $line=trim($line); if($line==$pid){ returntrue; }else{ if(empty($output)){ returnfalse; }else{ if(php_sapi_name()=='cli') $n="\n"; else $n="<br>"; //到这一步的话应该是出什么问题了 $output=implode($n,$output); debug_print($output,E_USER_WARNING); returntrue; } } }else{ returnfalse; } }
}