麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > PHP > 正文

分享PHP守護進程類

2024-05-04 23:41:44
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了PHP守護進程類,守護進程(Daemon)是運行在后臺的一種特殊進程。它獨立于控制終端并且周期性地執行某種任務或等待處理某些發生的事件。守護進程是一種很有用的進程。php也可以實現守護進程的功能,需要的朋友可以參考下
 

用PHP實現的Daemon類。可以在服務器上實現隊列或者脫離 crontab 的計劃任務。  
使用的時候,繼承于這個類,并重寫 _doTask 方法,通過 main 初始化執行。

<?php class Daemon {   const DLOG_TO_CONSOLE = 1;  const DLOG_NOTICE = 2;  const DLOG_WARNING = 4;  const DLOG_ERROR = 8;  const DLOG_CRITICAL = 16;   const DAPC_PATH = '/tmp/daemon_apc_keys';   /**   * User ID   *   * @var int   */  public $userID = 65534; // nobody   /**   * Group ID   *   * @var integer   */  public $groupID = 65533; // nobody   /**   * Terminate daemon when set identity failure ?   *   * @var bool   * @since 1.0.3   */  public $requireSetIdentity = false;   /**   * Path to PID file   *   * @var string   * @since 1.0.1   */  public $pidFileLocation = '/tmp/daemon.pid';   /**   * processLocation   * 進程信息記錄目錄   *   * @var string   */  public $processLocation = '';   /**   * processHeartLocation   * 進程心跳包文件   *   * @var string   */  public $processHeartLocation = '';   /**   * Home path   *   * @var string   * @since 1.0   */  public $homePath = '/';   /**   * Current process ID   *   * @var int   * @since 1.0   */  protected $_pid = 0;   /**   * Is this process a children   *   * @var boolean   * @since 1.0   */  protected $_isChildren = false;   /**   * Is daemon running   *   * @var boolean   * @since 1.0   */  protected $_isRunning = false;   /**   * Constructor   *   * @return void   */  public function __construct() {     error_reporting(0);    set_time_limit(0);    ob_implicit_flush();     register_shutdown_function(array(&$this, 'releaseDaemon'));  }   /**   * 啟動進程   *   * @return bool   */  public function main() {     $this->_logMessage('Starting daemon');     if (!$this->_daemonize()) {      $this->_logMessage('Could not start daemon', self::DLOG_ERROR);       return false;    }     $this->_logMessage('Running...');     $this->_isRunning = true;     while ($this->_isRunning) {      $this->_doTask();    }     return true;  }   /**   * 停止進程   *   * @return void   */  public function stop() {     $this->_logMessage('Stoping daemon');     $this->_isRunning = false;  }   /**   * Do task   *   * @return void   */  protected function _doTask() {    // override this method  }   /**   * _logMessage   * 記錄日志   *   * @param string 消息   * @param integer 級別   * @return void   */  protected function _logMessage($msg, $level = self::DLOG_NOTICE) {    // override this method  }   /**   * Daemonize   *   * Several rules or characteristics that most daemons possess:   * 1) Check is daemon already running   * 2) Fork child process   * 3) Sets identity   * 4) Make current process a session laeder   * 5) Write process ID to file   * 6) Change home path   * 7) umask(0)   *   * @access private   * @since 1.0   * @return void   */  private function _daemonize() {     ob_end_flush();     if ($this->_isDaemonRunning()) {      // Deamon is already running. Exiting      return false;    }     if (!$this->_fork()) {      // Coudn't fork. Exiting.      return false;    }     if (!$this->_setIdentity() && $this->requireSetIdentity) {      // Required identity set failed. Exiting      return false;    }     if (!posix_setsid()) {      $this->_logMessage('Could not make the current process a session leader', self::DLOG_ERROR);       return false;    }     if (!$fp = fopen($this->pidFileLocation, 'w')) {      $this->_logMessage('Could not write to PID file', self::DLOG_ERROR);      return false;    } else {      fputs($fp, $this->_pid);      fclose($fp);    }     // 寫入監控日志    $this->writeProcess();     chdir($this->homePath);    umask(0);     declare(ticks = 1);     pcntl_signal(SIGCHLD, array(&$this, 'sigHandler'));    pcntl_signal(SIGTERM, array(&$this, 'sigHandler'));    pcntl_signal(SIGUSR1, array(&$this, 'sigHandler'));    pcntl_signal(SIGUSR2, array(&$this, 'sigHandler'));     return true;  }   /**   * Cheks is daemon already running   *   * @return bool   */  private function _isDaemonRunning() {     $oldPid = file_get_contents($this->pidFileLocation);     if ($oldPid !== false && posix_kill(trim($oldPid),0))    {      $this->_logMessage('Daemon already running with PID: '.$oldPid, (self::DLOG_TO_CONSOLE | self::DLOG_ERROR));       return true;    }    else    {      return false;    }  }   /**   * Forks process   *   * @return bool   */  private function _fork() {     $this->_logMessage('Forking...');     $pid = pcntl_fork();     if ($pid == -1) {      // 出錯      $this->_logMessage('Could not fork', self::DLOG_ERROR);       return false;    } elseif ($pid) {      // 父進程      $this->_logMessage('Killing parent');       exit();    } else {      // fork的子進程      $this->_isChildren = true;      $this->_pid = posix_getpid();       return true;    }  }   /**   * Sets identity of a daemon and returns result   *   * @return bool   */  private function _setIdentity() {     if (!posix_setgid($this->groupID) || !posix_setuid($this->userID))    {      $this->_logMessage('Could not set identity', self::DLOG_WARNING);       return false;    }    else    {      return true;    }  }   /**   * Signals handler   *   * @access public   * @since 1.0   * @return void   */  public function sigHandler($sigNo) {     switch ($sigNo)    {      case SIGTERM:  // Shutdown        $this->_logMessage('Shutdown signal');        exit();        break;       case SIGCHLD:  // Halt        $this->_logMessage('Halt signal');        while (pcntl_waitpid(-1, $status, WNOHANG) > 0);        break;      case SIGUSR1:  // User-defined        $this->_logMessage('User-defined signal 1');        $this->_sigHandlerUser1();        break;      case SIGUSR2:  // User-defined        $this->_logMessage('User-defined signal 2');        $this->_sigHandlerUser2();        break;    }  }   /**   * Signals handler: USR1   * 主要用于定時清理每個進程里被緩存的域名dns解析記錄   *   * @return void   */  protected function _sigHandlerUser1() {    apc_clear_cache('user');  }   /**   * Signals handler: USR2   * 用于寫入心跳包文件   *   * @return void   */  protected function _sigHandlerUser2() {     $this->_initProcessLocation();     file_put_contents($this->processHeartLocation, time());     return true;  }   /**   * Releases daemon pid file   * This method is called on exit (destructor like)   *   * @return void   */  public function releaseDaemon() {     if ($this->_isChildren && is_file($this->pidFileLocation)) {      $this->_logMessage('Releasing daemon');       unlink($this->pidFileLocation);    }  }   /**   * writeProcess   * 將當前進程信息寫入監控日志,另外的腳本會掃描監控日志的數據發送信號,如果沒有響應則重啟進程   *   * @return void   */  public function writeProcess() {     // 初始化 proc    $this->_initProcessLocation();     $command = trim(implode(' ', $_SERVER['argv']));     // 指定進程的目錄    $processDir = $this->processLocation . '/' . $this->_pid;    $processCmdFile = $processDir . '/cmd';    $processPwdFile = $processDir . '/pwd';     // 所有進程所在的目錄    if (!is_dir($this->processLocation)) {      mkdir($this->processLocation, 0777);      chmod($processDir, 0777);    }     // 查詢重復的進程記錄    $pDirObject = dir($this->processLocation);    while ($pDirObject && (($pid = $pDirObject->read()) !== false)) {      if ($pid == '.' || $pid == '..' || intval($pid) != $pid) {        continue;      }       $pDir = $this->processLocation . '/' . $pid;      $pCmdFile = $pDir . '/cmd';      $pPwdFile = $pDir . '/pwd';      $pHeartFile = $pDir . '/heart';       // 根據cmd檢查啟動相同參數的進程      if (is_file($pCmdFile) && trim(file_get_contents($pCmdFile)) == $command) {        unlink($pCmdFile);        unlink($pPwdFile);        unlink($pHeartFile);         // 刪目錄有緩存        usleep(1000);         rmdir($pDir);      }    }     // 新進程目錄    if (!is_dir($processDir)) {      mkdir($processDir, 0777);      chmod($processDir, 0777);    }     // 寫入命令參數    file_put_contents($processCmdFile, $command);    file_put_contents($processPwdFile, $_SERVER['PWD']);     // 寫文件有緩存    usleep(1000);     return true;  }   /**   * _initProcessLocation   * 初始化   *   * @return void   */  protected function _initProcessLocation() {     $this->processLocation = ROOT_PATH . '/app/data/proc';    $this->processHeartLocation = $this->processLocation . '/' . $this->_pid . '/heart';  }}


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 国产亚洲精品久久久久久久 | 8x成人在线电影 | 欧美久久久久久久久 | 成人毛片100免费观看 | 久久久日韩精品一区二区三区 | 成人三级黄色片 | 在线看一区二区三区 | 久久精品一区二区三区四区五区 | 一级黄色片武则天 | 欧美特级一级毛片 | 毛片免费视频观看 | 欧美视屏一区二区 | 日本中文一级片 | 一区二区久久精品66国产精品 | 国产色视频一区 | 天天夜夜操操 | 日韩精品99久久久久久 | 欧美一级特黄aaaaaaa什 | 国产精品亚洲综合一区二区三区 | 蜜桃传媒视频麻豆第一区免费观看 | 欧美a级在线免费观看 | 在线成人一区二区 | av在线免费观看网 | 国产午夜电影在线观看 | 中文字幕线观看 | 天堂精品久久 | 中文字幕一二三区芒果 | 欧美18—19sex性hd | 久艹在线视频 | 久久精品视频免费 | 黄色1级视频 | 亚洲一区二区三区四区精品 | 国产超碰人人爽人人做人人爱 | 日韩一级免费 | 天天艹综合 | 成人国产精品一区 | 麻豆一二区 | a黄色片| 欧美激情性色生活片在线观看 | 色av综合在线 | 久久精品成人影院 |