489 lines
8.4 KiB
PHP
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
?>
|