идеальный: есть ситуации, при которых он не будет работать корректно. Это
связано с тем, что pid процессов имеют свойство повторяться
class SameProccessChecker {
protected $_filename;
protected $_dir;
/**
* @param string $filename желаемое имя файла для маркерного файла
* @param string $dir желаемая директория для маркерного файла
*/
public function __construct($filename = NULL, $dir = NULL) {
$this->_filename = $filename !== NULL ? $filename :
"pid.lock";
$this->_dir = $dir !== NULL ? $dir :
dirname(__FILE__)."/";
}
/**
* Проверяет, существует ли уже такой процесс
*
* @return bool
* @throws Exception
*/
public function isProcessExists()
{
$filename = $this->_dir.$this->_filename;
if(file_exists($filename)) {
if(is_readable($filename)) {
$is_pid_running =
file_exists("/proc/".(int)file_get_contents($filename));
if($is_pid_running) {
return true;
} else {
unlink($filename);
}
} else {
throw new Exception("Lock file ".$filename."
is not readable");
}
}
return false;
}
/**
* @return bool|int
* @throws Exception
*/
public function writePID()
{
if(!file_exists($this->_dir) && !mkdir($this->_dir, 0755,
true)) {
throw new Exception("Cannot create directory
".$this->_dir);
}
$pid = getmypid();
$filename = $this->_dir.$this->_filename;
if(!file_exists($filename)) {
return file_put_contents($filename, $pid);
}
return false;
}
}
И пример использования
// В самом начале программы
$PIDChecker = new SameProccessChecker();
if(!$PIDChecker->isProcessExists() && $PIDChecker->writePID()) {
// Полезный код
} else {
// такой процесс уже есть
die();
}