Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Demon w PHP, Klasa bazowa, Klasa, PHP 4 i 5, Unix
Seth
post 22.03.2005, 19:01:07
Post #1





Grupa: Przyjaciele php.pl
Postów: 2 335
Pomógł: 6
Dołączył: 7.03.2002

Ostrzeżenie: (0%)
-----


Daemon.class.php:
  1. <?php
  2. /**
  3. * @package binarychoice.system.unix
  4. * @since 1.0
  5. */
  6.  
  7. // Log message levels
  8. define('DLOG_TO_CONSOLE', 1);
  9. define('DLOG_NOTICE',  2);
  10. define('DLOG_WARNING', 4);
  11. define('DLOG_ERROR', 8);
  12. define('DLOG_CRITICAL',  16);
  13.  
  14. /**
  15. * Daemon base class
  16. *
  17. * Requirements:
  18. * Unix like operating system
  19. * php 4 >= 4.3.0 or php 5
  20. * php compiled with:
  21. * --enable-sigchild
  22. * --enable-pcntl
  23. *
  24. * @package binarychoice.system.unix
  25. * @author Michal 'Seth' Golebiowski <seth@binarychoice.pl>
  26. * @copyright Copyright 2005 BinaryChoice
  27. * @since 1.0
  28. */
  29. class Daemon
  30. {
  31. /**#@+
  32.  * @access public
  33.  */
  34. /**
  35.  * User ID
  36.  * @var int
  37.  * @since 1.0
  38.  */
  39. var $userID = 99;
  40.  
  41. /**
  42.  * Group ID
  43.  * @var integer
  44.  * @since 1.0
  45.  */
  46. var $groupID = 99;
  47.  
  48. /**
  49.  * Path to PID file name
  50.  * @var string
  51.  * @since 1.0
  52.  */
  53. var $pidFullPath = '/tmp/daemon.pid';
  54.  
  55. /**
  56.  * Home path
  57.  * @var string
  58.  * @since 1.0
  59.  */
  60. var $homePath = '/';
  61. /**#@-*/
  62.  
  63.  
  64. /**#@+
  65.  * @access private
  66.  */
  67. /**
  68.  * Current process ID
  69.  * @var int
  70.  * @since 1.0
  71.  */
  72. var $_pid = 0;
  73.  
  74. /**
  75.  * Is this process a children
  76.  * @var boolean
  77.  * @since 1.0
  78.  */
  79. var $_isChildren = false;
  80.  
  81. /**
  82.  * Is daemon running
  83.  * @var boolean
  84.  * @since 1.0
  85.  */
  86. var $_isRunning = false;
  87. /**#@-*/
  88.  
  89.  
  90. /**
  91.  * Constructor
  92.  *
  93.  * @access public
  94.  * @since 1.0
  95.  * @return void
  96.  */
  97. function Daemon()
  98. {
  99.  
  100. register_shutdown_function(array(&$this, 'releaseDaemon'));
  101. }
  102.  
  103. /**
  104.  * Starts daemon
  105.  *
  106.  * @access public
  107.  * @since 1.0
  108.  * @return void
  109.  */
  110. function start()
  111. {
  112. $this->_logMessage('Starting daemon');
  113.  
  114. if (!$this->_daemonize())
  115. {
  116. $this>_logMessage('Could not start daemon', DLOG_ERROR);
  117.  
  118. return false;
  119. }
  120.  
  121. $this->_logMessage('Running...');
  122.  
  123.  
  124. $this->_isRunning = true;
  125.  
  126. while ($this->_isRunning)
  127. {
  128.  
  129. $this->_doTask();
  130. }
  131.  
  132. return true;
  133. }
  134.  
  135. /**
  136.  * Stops daemon
  137.  *
  138.  * @access public
  139.  * @since 1.0
  140.  * @return void
  141.  */
  142. function stop()
  143. {
  144. $this->_logMessage('Stoping daemon');
  145.  
  146. $this->_isRunning = false;
  147. }
  148.  
  149. /**
  150.  * Do task
  151.  *
  152.  * @access protected
  153.  * @since 1.0
  154.  * @return void
  155.  */
  156. function _doTask()
  157. {
  158. }
  159.  
  160. /**
  161.  * Logs message
  162.  *
  163.  * @access protected
  164.  * @since 1.0
  165.  * @return void
  166.  */
  167. function _logMessage($msg, $level = DLOG_NOTICE)
  168. {
  169. }
  170.  
  171. /**
  172.  * Daemonize
  173.  *
  174.  * @access private
  175.  * @since 1.0
  176.  * @return void
  177.  */
  178. function _daemonize()
  179. {
  180.  
  181. $this->_setIdentity();
  182.  
  183. if ($this->_isDaemonAlreadyRunning())
  184. {
  185. return false;
  186. }
  187.  
  188. if (!$this->_fork())
  189. {
  190. return false;
  191. }
  192.  
  193. if (!posix_setsid())
  194. {
  195. $this->_logMessage('Could not make the current process a session leader', DLOG_ERROR);
  196.  
  197. return false;
  198. }
  199.  
  200. if ( !$fp = fopen($this->pidFullPath, 'w') )
  201. {
  202. $this->_logMessage('Could not write to PID file', DLOG_ERROR);
  203.  
  204. return false;
  205. }
  206. else
  207. {
  208. fputs($fp, $this->_pid);
  209. fclose($fp);
  210. }
  211.  
  212. chdir($this->homePath);
  213. umask(0);
  214.  
  215. pcntl_signal(SIGCHLD, array(&$this, 'sigHandler'));
  216. pcntl_signal(SIGTERM, array(&$this, 'sigHandler'));
  217.  
  218. return true;
  219. }
  220.  
  221. /**
  222.  * Cheks is daemon already running
  223.  *
  224.  * @access private
  225.  * @since 1.0
  226.  * @return bool
  227.  */
  228. function _isDaemonAlreadyRunning()
  229. {
  230. $oldPid = file_get_contents($this->pidFullPath);
  231.  
  232. if ($oldPid !== false && posix_kill(trim($oldPid),0))
  233. {
  234. $this->_logMessage('Daemon already running with PID: '.$oldPid, (DLOG_TO_CONSOLE | DLOG_ERROR));
  235.  
  236. return true;
  237. }
  238. else
  239. {
  240. return false;
  241. }
  242. }
  243.  
  244. /**
  245.  * Forks process
  246.  *
  247.  * @access private
  248.  * @since 1.0
  249.  * @return bool
  250.  */
  251. function _fork()
  252. {
  253. $this->_logMessage('Forking...');
  254.  
  255. $pid = pcntl_fork();
  256.  
  257. if ($pid == -1)
  258. {
  259. $this->_logMessage('Could not fork', DLOG_ERROR);
  260.  
  261. return false;
  262. }
  263. else if ($pid)
  264. {
  265. $this->_logMessage('Killing parent');
  266.  
  267. exit();
  268. }
  269. else
  270. {
  271. $this->_isChildren = true;
  272. $this->_pid = posix_getpid();
  273.  
  274. return true;
  275. }
  276. }
  277.  
  278. /**
  279.  * Sets identity of a daemon and returns result
  280.  *
  281.  * @access private
  282.  * @since 1.0
  283.  * @return bool
  284.  */
  285. function _setIdentity()
  286. {
  287. if (!posix_setgid($this->groupID) || !posix_setuid($this->userID))
  288. {
  289. $this->_logMessage('Could not set identity', DLOG_WARNING);
  290.  
  291. return false;
  292. }
  293. else
  294. {
  295. return true;
  296. }
  297. }
  298.  
  299. /**
  300.  * Signals handler
  301.  *
  302.  * @access public
  303.  * @since 1.0
  304.  * @return void
  305.  */
  306. function sigHandler($sigNo)
  307. {
  308. switch ($sigNo)
  309. {
  310. case SIGTERM: // Shutdown
  311. $this->_logMessage('Shutdown signal');
  312. exit();
  313. break;
  314.  
  315. case SIGCHLD: // Halt
  316. $this->_logMessage('Halt signal');
  317. while (pcntl_waitpid(-1, $status, WNOHANG) > 0);
  318. break;
  319. }
  320. }
  321.  
  322. /**
  323.  * Releases daemon pid file
  324.  * This method is called on exit
  325.  *
  326.  * @access public
  327.  * @since 1.0
  328.  * @return void
  329.  */
  330. function releaseDaemon()
  331. {
  332. if (!$this->_isChildren && file_exists($this->$pidFileName))
  333. {
  334. $this->_logMessage('Releasing daemon');
  335.  
  336. unlink($this->$pidFileName);
  337. }
  338. }
  339. }
  340. ?>


Prosty przyklad demona (TestDaemon.class.php):
  1. <?php
  2. class TestDaemon extends Daemon
  3. {
  4.  function TestDaemon()
  5.  {
  6. parent::Daemon();
  7.  
  8. $fp = fopen('/tmp/daemon.log', 'a');
  9. fclose($fp);
  10.  
  11. chmod('/tmp/daemon.log', 0777);
  12.  }
  13.  
  14.  function _logMessage($msg, $status = DLOG_NOTICE)
  15.  {
  16. if ($status & DLOG_TO_CONSOLE)
  17. {
  18.  print $msg.&#092;"n\";
  19. }
  20.  
  21. $fp = fopen('/tmp/daemon.log', 'a');
  22. fwrite($fp, date(&#092;"Y/m/d H:i:s \").$msg.\"n\");
  23. fclose($fp);
  24.  }
  25.  
  26.  function _doTask()
  27.  {
  28. static $i = 0;
  29.  
  30. sleep(1);
  31.  
  32. $i++;
  33.  
  34. if ($i >= 30)
  35. {
  36.  $this->stop();
  37. }
  38.  }
  39.  
  40. }
  41. ?>


Plik uruchamiajacy testowego demona (run.php):
  1. <?php
  2. require_once ('Daemon.class.php');
  3. require_once ('TestDaemon.class.php');
  4.  
  5. $Daemon = new TestDaemon();
  6. $Daemon->start();
  7. ?>


run.php uruchamiamy oczywiscie z konsoli.

Wiecej infromacji na mojej stronie domowej smile.gif
Go to the top of the page
+Quote Post
darkspirit
post 24.03.2005, 11:20:21
Post #2





Grupa: Zarejestrowani
Postów: 19
Pomógł: 0
Dołączył: 13.08.2004
Skąd: Łódź

Ostrzeżenie: (0%)
-----


fajnie, a przy tym oryginalne bo po raz pierwszy widzę, żeby ktoś ugryzł ten problem smile.gif

paps

Ten post edytował darkspirit 24.03.2005, 11:20:37


--------------------
Apache 1.3.31 PHP 4.3.10 && 5.0.3 Go to the top of the page
+Quote Post
Seth
post 4.04.2005, 21:45:07
Post #3





Grupa: Przyjaciele php.pl
Postów: 2 335
Pomógł: 6
Dołączył: 7.03.2002

Ostrzeżenie: (0%)
-----


Dzieki smile.gif

Dodam, jeszce ze kod mozna sciagnac stad:
http://www.phpclasses.org/browse/package/2197.html
(tam jest najaktualniejsza wersja)
Go to the top of the page
+Quote Post
bela
post 4.04.2005, 22:09:20
Post #4


Administrator PHPedia.pl


Grupa: Developerzy
Postów: 1 102
Pomógł: 2
Dołączył: 14.09.2003

Ostrzeżenie: (0%)
-----


No proszę,
Cytat
Innovation Award: March 2005 Nominee

winksmiley.jpg


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 16.04.2024 - 23:05