Files
zurawik.pl/core/class/Daemon.class.php
2026-05-15 18:33:51 +02:00

489 lines
8.4 KiB
PHP

<?php
// Logowanie
define('DLOG_TO_CONSOLE', 1);
define('DLOG_NOTICE', 2);
define('DLOG_WARNING', 4);
define('DLOG_ERROR', 8);
define('DLOG_CRITICAL', 16);
/**
* Daemon
*
* Wymagania:
* Unix
* PHP 4 >= 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);
}
}
}
?>