Table des matières
分享PHP守护进程类,分享php守护进程
您可能感兴趣的文章:
Maison php教程 php手册 分享PHP守护进程类,分享php守护进程

分享PHP守护进程类,分享php守护进程

Jun 13, 2016 am 08:48 AM
php 守护进程

分享PHP守护进程类,分享php守护进程

用PHP实现的Daemon类。可以在服务器上实现队列或者脱离 crontab 的计划任务。 
使用的时候,继承于这个类,并重写 _doTask 方法,通过 main 初始化执行。

<&#63;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 &#63;
   *
   * @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';
  }
}
Copier après la connexion

您可能感兴趣的文章:

  • php守护进程 加linux命令nohup实现任务每秒执行一次
  • PHP程序级守护进程的实现与优化的使用概述
  • PHP实现多进程并行操作的详解(可做守护进程)
  • shell脚本作为保证PHP脚本不挂掉的守护进程实例分享
  • PHP高级编程实例:编写守护进程
  • PHP守护进程实例
  • PHP将进程作为守护进程的方法
  • PHP扩展程序实现守护进程
  • 如何写php守护进程(Daemon)
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Repo: Comment relancer ses coéquipiers
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Configuration du projet CakePHP Configuration du projet CakePHP Sep 10, 2024 pm 05:25 PM

Dans ce chapitre, nous comprendrons les variables d'environnement, la configuration générale, la configuration de la base de données et la configuration de la messagerie dans CakePHP.

Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 apporte plusieurs nouvelles fonctionnalités, améliorations de sécurité et de performances avec une bonne quantité de dépréciations et de suppressions de fonctionnalités. Ce guide explique comment installer PHP 8.4 ou mettre à niveau vers PHP 8.4 sur Ubuntu, Debian ou leurs dérivés. Bien qu'il soit possible de compiler PHP à partir des sources, son installation à partir d'un référentiel APT comme expliqué ci-dessous est souvent plus rapide et plus sécurisée car ces référentiels fourniront les dernières corrections de bogues et mises à jour de sécurité à l'avenir.

Date et heure de CakePHP Date et heure de CakePHP Sep 10, 2024 pm 05:27 PM

Pour travailler avec la date et l'heure dans cakephp4, nous allons utiliser la classe FrozenTime disponible.

Téléchargement de fichiers CakePHP Téléchargement de fichiers CakePHP Sep 10, 2024 pm 05:27 PM

Pour travailler sur le téléchargement de fichiers, nous allons utiliser l'assistant de formulaire. Voici un exemple de téléchargement de fichiers.

Routage CakePHP Routage CakePHP Sep 10, 2024 pm 05:25 PM

Dans ce chapitre, nous allons apprendre les sujets suivants liés au routage ?

Discuter de CakePHP Discuter de CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP est un framework open source pour PHP. Il vise à faciliter grandement le développement, le déploiement et la maintenance d'applications. CakePHP est basé sur une architecture de type MVC à la fois puissante et facile à appréhender. Modèles, vues et contrôleurs gu

Comment configurer Visual Studio Code (VS Code) pour le développement PHP Comment configurer Visual Studio Code (VS Code) pour le développement PHP Dec 20, 2024 am 11:31 AM

Visual Studio Code, également connu sous le nom de VS Code, est un éditeur de code source gratuit – ou environnement de développement intégré (IDE) – disponible pour tous les principaux systèmes d'exploitation. Avec une large collection d'extensions pour de nombreux langages de programmation, VS Code peut être c

CakePHP créant des validateurs CakePHP créant des validateurs Sep 10, 2024 pm 05:26 PM

Le validateur peut être créé en ajoutant les deux lignes suivantes dans le contrôleur.

See all articles