<?php /** * @package binarychoice.system.unix * @since 1.0 */ // Log message levels /** * Daemon base class * * Requirements: * Unix like operating system * php 4 >= 4.3.0 or php 5 * php compiled with: * --enable-sigchild * --enable-pcntl * * @package binarychoice.system.unix * @author Michal 'Seth' Golebiowski <seth@binarychoice.pl> * @copyright Copyright 2005 BinaryChoice * @since 1.0 */ class Daemon { /**#@+ * @access public */ /** * User ID * @var int * @since 1.0 */ var $userID = 99; /** * Group ID * @var integer * @since 1.0 */ var $groupID = 99; /** * Path to PID file name * @var string * @since 1.0 */ var $pidFullPath = '/tmp/daemon.pid'; /** * Home path * @var string * @since 1.0 */ var $homePath = '/'; /**#@-*/ /**#@+ * @access private */ /** * Current process ID * @var int * @since 1.0 */ var $_pid = 0; /** * Is this process a children * @var boolean * @since 1.0 */ var $_isChildren = false; /** * Is daemon running * @var boolean * @since 1.0 */ var $_isRunning = false; /**#@-*/ /** * Constructor * * @access public * @since 1.0 * @return void */ function Daemon() { } /** * Starts daemon * * @access public * @since 1.0 * @return void */ function start() { $this->_logMessage('Starting daemon'); if (!$this->_daemonize()) { $this>_logMessage('Could not start daemon', DLOG_ERROR); return false; } $this->_logMessage('Running...'); $this->_isRunning = true; while ($this->_isRunning) { $this->_doTask(); } return true; } /** * Stops daemon * * @access public * @since 1.0 * @return void */ function stop() { $this->_logMessage('Stoping daemon'); $this->_isRunning = false; } /** * Do task * * @access protected * @since 1.0 * @return void */ function _doTask() { } /** * Logs message * * @access protected * @since 1.0 * @return void */ function _logMessage($msg, $level = DLOG_NOTICE) { } /** * Daemonize * * @access private * @since 1.0 * @return void */ function _daemonize() { $this->_setIdentity(); if ($this->_isDaemonAlreadyRunning()) { return false; } if (!$this->_fork()) { return false; } if (!posix_setsid()) { $this->_logMessage('Could not make the current process a session leader', DLOG_ERROR); return false; } { $this->_logMessage('Could not write to PID file', DLOG_ERROR); return false; } else { } return true; } /** * Cheks is daemon already running * * @access private * @since 1.0 * @return bool */ function _isDaemonAlreadyRunning() { { $this->_logMessage('Daemon already running with PID: '.$oldPid, (DLOG_TO_CONSOLE | DLOG_ERROR)); return true; } else { return false; } } /** * Forks process * * @access private * @since 1.0 * @return bool */ function _fork() { $this->_logMessage('Forking...'); $pid = pcntl_fork(); if ($pid == -1) { $this->_logMessage('Could not fork', DLOG_ERROR); return false; } else if ($pid) { $this->_logMessage('Killing parent'); } else { $this->_isChildren = true; $this->_pid = posix_getpid(); return true; } } /** * Sets identity of a daemon and returns result * * @access private * @since 1.0 * @return bool */ function _setIdentity() { if (!posix_setgid($this->groupID) || !posix_setuid($this->userID)) { $this->_logMessage('Could not set identity', DLOG_WARNING); return false; } else { return true; } } /** * Signals handler * * @access public * @since 1.0 * @return void */ function sigHandler($sigNo) { switch ($sigNo) { case SIGTERM: // Shutdown $this->_logMessage('Shutdown signal'); break; case SIGCHLD: // Halt $this->_logMessage('Halt signal'); while (pcntl_waitpid(-1, $status, WNOHANG) > 0); break; } } /** * Releases daemon pid file * This method is called on exit * * @access public * @since 1.0 * @return void */ function releaseDaemon() { { $this->_logMessage('Releasing daemon'); } } } ?>
Prosty przyklad demona (TestDaemon.class.php):
<?php class TestDaemon extends Daemon { function TestDaemon() { parent::Daemon(); chmod('/tmp/daemon.log', 0777); } function _logMessage($msg, $status = DLOG_NOTICE) { if ($status & DLOG_TO_CONSOLE) { } } function _doTask() { $i++; if ($i >= 30) { $this->stop(); } } } ?>
Plik uruchamiajacy testowego demona (run.php):
<?php require_once ('Daemon.class.php'); require_once ('TestDaemon.class.php'); $Daemon = new TestDaemon(); $Daemon->start(); ?>
run.php uruchamiamy oczywiscie z konsoli.
Wiecej infromacji na mojej stronie domowej
