= 4.3.0 or PHP 5 * PHP z: * --enable-sigchild * --enable-pcntl */ class Daemon { private $userID = 99; public $x=0; private $groupID = 99; /** * Zakonczyc prace gdy nie da sie ustawic tozsamosci demona ? */ private $requireSetIdentity = false; /** * sciezka do pida * */ private $pidFileLocation = '/home/users/turystyka/public_html/test/daemon.pid'; /** * sciezka home'a.. tylko po co? * */ private $homePath = '/home/users/turystyka/public_html/Server/Daemon'; /** * id procesu * */ protected $pid = 0; /** * czy proces jest dzieckiem * */ private $isChildren = false; /** * czy dzialamy czy nie :) * */ private $isRunning = false; private $children = array(); private $maxProcesses = 10; /** * Konstruktor */ public function __construct($homePath, $pidFileLocation) { error_reporting(0); set_time_limit(0); ob_implicit_flush(); register_shutdown_function(array(&$this, 'releaseDaemon')); } public function GetUserID() { return $this->userID; } public function SetUserID($userID) { $this->userID = $userID; } public function GetGroupID() { return $this->groupID; } public function SetGroupID($groupID) { $this->groupID = $groupID; } public function GetRequireSetIdentity() { return $this->requireSetIdentity; } public function SetRequireSetIdentity($requireSetIdentity) { $this->requireSetIdentity = $requireSetIdentity; } public function GetPidFileLocation() { return $this->pidFileLocation; } public function SetPidFileLocation($pidFileLocation) { $this->pidFileLocation = $pidFileLocation; } public function GetHomePath() { return $this->homePath; } public function SetHomePath($homePath) { $this->homePath = $homePath; } public function GetPid() { return $this->pid; } public function SetPid($pid) { $this->pid = $pid; $fp = fopen($this->GetHomePath().'/'.$this->pid.'.pid', 'w'); fwrite($fp, serialize($this)); fclose($fp); } public function GetIsChildren() { return $this->isChildren; } public function SetIsChildren($isChildren) { $this->isChildren = $isChildren; } public function GetIsRunning() { return $this->isRunning; } public function SetIsRunning($isRunning) { $this->isRunning = $isRunning; } public function GetChildren() { return $this->children; } public function AddChild($pid) { $this->children[$pid] = true; } public function RemChild($pid) { if(isset($this->children[$pid])) { unset($this->childern[$pid]); } } public function StartChild($child) { $pid = Daemon::InitChild($chils, $this->GetPid()); $this->AddChild($pid); MFLog::DbLog('Child process '.$pid.' started'); if(!is_dir($filename)) { mkdir($this->GetHomePath().'/'.$this->GetPid(), 0777); } $fp = fopen($this->GetHomePath().'/'.$this->GetPid().'/'.$pid.'.pid', 'w'); fwrite($fp, serialize($child)); fclose($fp); $pidReturn = pcntl_waitpid($pid, $status); if(pcntl_wifexited($status)) { MFLog::DbLog('Child process '.$pid.' finished with status: '.$status); } else { MFLog::DbLog('child process '.$pid.' died'); } return true; } public static function InitChild($child, $masterPid) { $pid = pcntl_fork(); if($pid == 0) { exit($child->Run($masterPid)); } else { return $pid; } } public function KillAll() { foreach($this->GetChildren() as $pid => $data) { MFLog::DbLog('Killing: '.$pid); posix_kill($pid, 0); if(is_file($this->GetHomePath().'/'.$this->GetPid().'/'.$pid.'.pid')) { unlink($this->GetHomePath().'/'.$this->GetPid().'/'.$pid.'.pid'); } } } /** * Inicjowanie komponentow systemu * */ public function Init() { //include('class/DB.class.php'); //include('class/Registry.class.php'); //include('ErrorHandler.php'); $db = new DBProd(); Registry::Remove('db'); Registry::Set('db', $db); } /** * Start daemona * */ public 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; } /** * Stop daemona * */ public function Stop() { $this->LogMessage('Stoping daemon'); $this->KillAll(); if(is_file($this->GetHomePath().'/'.$this->pid.'.pid')) { unlink($this->GetHomePath().'/'.$this->pid.'.pid'); } $this->IsRunning = false; //posix_kill($this->GetPid(), 0); //exit; } /** * Podaj lape :) * */ function DoTask() { while(1) { if(is_dir($this->GetHomePath().'/todo')) { if($handle = opendir($this->GetHomePath().'/todo')) { while (false !== ($file = readdir($handle))) { if(count($this->GetChildren()) < $this->maxProcesses) { $taskFile = fopen($this->GetHomePath().'/todo/'.$file, 'r'); $taskData = fread($taskFile, filesize($this->GetHomePath().'/todo/'.$file)); fclose($taskFile); unlink($this->GetHomePath().'/todo/'.$file); $taskObj = unserialize($taskData); $this->InitChild($taskObj, $this->GetPid()); } } } } } // hau hau //mail('pawy@formix.pl', 'demonizer', 'im running'); // $fp = fopen('/home/users/turystyka/public_html/test/data'.$this->x.'.txt', 'w'); // fwrite($fp, '1'); // fwrite($fp, '23'); // fclose($fp); // sleep(10); // //$fp = fopen('/home/users/turystyka/public_html/test/data2.txt', 'w'); // $this->x++; // if($this->x < 5){ // $this->DoTask(); // } else { // $this->Stop(); // } } /** * Logujemy cos * */ public function LogMessage($msg, $level = DLOG_NOTICE) { // logowanie MFLog::DbLog($msg); } /** * Nie taki diabel straszny.. * */ private function Daemonize() { // ob_end_flush(); if ($this->IsDaemonRunning()) { // Deamon dziala. Exiting return false; } if (!$this->Fork()) { // niesforkowalo sie. Exiting. return false; } if (!$this->SetIdentity() && $this->requireSetIdentity) { // nie udalo sie ustawic tozsamosci. Exiting return false; } if (!posix_setsid()) { $this->LogMessage('Could not make the current process a session leader', DLOG_ERROR); return false; } if (!$fp = @fopen($this->pidFileLocation, 'w')) { $this->LogMessage('Could not write to PID file', DLOG_ERROR); return false; } else { fputs($fp, $this->pid); fclose($fp); } @chdir($this->homePath); umask(0); declare(ticks = 1); pcntl_signal(SIGCHLD, array(&$this, 'sigHandler')); pcntl_signal(SIGTERM, array(&$this, 'sigHandler')); return true; } /** * sprawdzamy czy dzialamy juz * */ private function IsDaemonRunning() { $oldPid = false; if(is_file($this->pidFileLocation)) { $oldPid = @file_get_contents($this->pidFileLocation); } if ($oldPid !== false && posix_kill(trim($oldPid),0)) { $this->LogMessage('Daemon already running with PID: '.$oldPid, (DLOG_TO_CONSOLE | DLOG_ERROR)); return true; } else { return false; } } /** * Forkujemy proces */ private function Fork() { $this->LogMessage('Forking...'); $pid = pcntl_fork(); if ($pid == -1) // error { $this->LogMessage('Could not fork', DLOG_ERROR); return false; } else if ($pid) // parent { $this->LogMessage('Killing parent'); exit(); } else // children { $this->IsChildren = true; $this->SetPid(posix_getpid()); return true; } } /** * Ustawiamy tozsamosc diobła i zwracamy wynik * */ private function SetIdentity() { if (!posix_setgid($this->groupID) || !posix_setuid($this->userID)) { $this->LogMessage('Could not set identity', DLOG_WARNING); return false; } else { return true; } } /** * Obsluga sig'ow * */ public function SigHandler($sigNo) { switch ($sigNo) { case SIGTERM: // Shutdown $this->LogMessage('Shutdown signal'); $this->Stop(); exit(); break; case SIGCHLD: // Halt $this->LogMessage('Halt signal'); while (pcntl_waitpid(-1, $status, WNOHANG) > 0); break; } } /** * Zwalnia plik z pidem * Cos ala desktruktor * */ public function ReleaseDaemon() { if (file_exists($this->pidFileLocation)) // if ($this->isChildren && file_exists($this->pidFileLocation)) { $this->LogMessage('Releasing daemon'); unlink($this->pidFileLocation); } } } ?>