PHP Daemon Class

Source: Internet
Author: User
Tags usleep
the Daemon class implemented in PHP. You can implement a queue on a server or a scheduled task that is out of crontab.
when used, it inherits from this class and overrides the _dotask method, which is executed through main initialization.
  1. Class Daemon {
  2. Const DLOG_TO_CONSOLE = 1;
  3. Const DLOG_NOTICE = 2;
  4. Const DLOG_WARNING = 4;
  5. Const DLOG_ERROR = 8;
  6. Const DLOG_CRITICAL = 16;
  7. Const Dapc_path = '/tmp/daemon_apc_keys ';
  8. /**
  9. * User ID
  10. *
  11. * @var int
  12. */
  13. Public $userID = 65534; Nobody
  14. /**
  15. * Group ID
  16. *
  17. * @var Integer
  18. */
  19. Public $groupID = 65533; Nobody
  20. /**
  21. * Terminate Daemon When set identity failure?
  22. *
  23. * @var BOOL
  24. * @since 1.0.3
  25. */
  26. Public $requireSetIdentity = false;
  27. /**
  28. * Path to PID file
  29. *
  30. * @var String
  31. * @since 1.0.1
  32. */
  33. Public $pidFileLocation = '/tmp/daemon.pid ';
  34. /**
  35. * Processlocation
  36. * Process Information Record directory
  37. *
  38. * @var String
  39. */
  40. Public $processLocation = ';
  41. /**
  42. * Processheartlocation
  43. * Process Heartbeat Package file
  44. *
  45. * @var String
  46. */
  47. Public $processHeartLocation = ';
  48. /**
  49. * Home Path
  50. *
  51. * @var String
  52. * @since 1.0
  53. */
  54. Public $homePath = '/';
  55. /**
  56. * Current Process ID
  57. *
  58. * @var int
  59. * @since 1.0
  60. */
  61. protected $_pid = 0;
  62. /**
  63. * Is this process a children
  64. *
  65. * @var Boolean
  66. * @since 1.0
  67. */
  68. protected $_ischildren = false;
  69. /**
  70. * Is daemon running
  71. *
  72. * @var Boolean
  73. * @since 1.0
  74. */
  75. protected $_isrunning = false;
  76. /**
  77. * Constructor
  78. *
  79. * @return void
  80. */
  81. Public Function __construct () {
  82. error_reporting (0);
  83. Set_time_limit (0);
  84. Ob_implicit_flush ();
  85. Register_shutdown_function (Array (& $this, ' Releasedaemon '));
  86. }
  87. /**
  88. * START Process
  89. *
  90. * @return BOOL
  91. */
  92. Public Function main () {
  93. $this->_logmessage (' starting daemon ');
  94. if (! $this->_daemonize ()) {
  95. $this->_logmessage (' Could not start daemon ', self::D log_error);
  96. return false;
  97. }
  98. $this->_logmessage (' Running ... ');
  99. $this->_isrunning = true;
  100. while ($this->_isrunning) {
  101. $this->_dotask ();
  102. }
  103. return true;
  104. }
  105. /**
  106. * Stop Process
  107. *
  108. * @return void
  109. */
  110. Public Function Stop () {
  111. $this->_logmessage (' stoping daemon ');
  112. $this->_isrunning = false;
  113. }
  114. /**
  115. * Do task
  116. *
  117. * @return void
  118. */
  119. protected function _dotask () {
  120. Override this method
  121. }
  122. /**
  123. * _logmessage
  124. * Record Log
  125. *
  126. * @param string message
  127. * @param integer level
  128. * @return void
  129. */
  130. protected function _logmessage ($msg, $level = self::D log_notice) {
  131. Override this method
  132. }
  133. /**
  134. * Daemonize
  135. *
  136. * Several rules or characteristics that most daemons possess:
  137. * 1) Check is daemon already running
  138. * 2) Fork child process
  139. * 3) Sets identity
  140. * 4) Make current process a session Laeder
  141. * 5) Write process ID to file
  142. * 6) Change Home path
  143. * 7) umask (0)
  144. *
  145. * @access Private
  146. * @since 1.0
  147. * @return void
  148. */
  149. Private Function _daemonize () {
  150. Ob_end_flush ();
  151. if ($this->_isdaemonrunning ()) {
  152. Deamon is already running. Exiting
  153. return false;
  154. }
  155. if (! $this->_fork ()) {
  156. Coudn ' t fork. Exiting.
  157. return false;
  158. }
  159. if (! $this->_setidentity () && $this->requiresetidentity) {
  160. Required identity set failed. Exiting
  161. return false;
  162. }
  163. if (!posix_setsid ()) {
  164. $this->_logmessage (' Could not make the current process a session leader ', self::D log_error);
  165. return false;
  166. }
  167. if (! $fp = fopen ($this->pidfilelocation, ' W ')) {
  168. $this->_logmessage (' Could not write-to-PID file ', self::D log_error);
  169. return false;
  170. } else {
  171. Fputs ($fp, $this->_pid);
  172. Fclose ($FP);
  173. }
  174. Writing to the monitoring log
  175. $this->writeprocess ();
  176. ChDir ($this->homepath);
  177. Umask (0);
  178. DECLARE (ticks = 1);
  179. Pcntl_signal (SIGCHLD, Array (& $this, ' Sighandler '));
  180. Pcntl_signal (SIGTERM, Array (& $this, ' Sighandler '));
  181. Pcntl_signal (SIGUSR1, Array (& $this, ' Sighandler '));
  182. Pcntl_signal (SIGUSR2, Array (& $this, ' Sighandler '));
  183. return true;
  184. }
  185. /**
  186. * Cheks is daemon already running
  187. *
  188. * @return BOOL
  189. */
  190. Private Function _isdaemonrunning () {
  191. $oldPid = file_get_contents ($this->pidfilelocation);
  192. if ($oldPid!== false && Posix_kill (Trim ($oldPid), 0))
  193. {
  194. $this->_logmessage (' Daemon already running with PID: '. $oldPid, (self::D log_to_console | self::D log_error));
  195. return true;
  196. }
  197. Else
  198. {
  199. return false;
  200. }
  201. }
  202. /**
  203. * Forks Process
  204. *
  205. * @return BOOL
  206. */
  207. Private Function _fork () {
  208. $this->_logmessage (' forking ... ');
  209. $pid = Pcntl_fork ();
  210. if ($pid = =-1) {
  211. Error
  212. $this->_logmessage (' Could not fork ', self::D log_error);
  213. return false;
  214. } elseif ($pid) {
  215. Parent process
  216. $this->_logmessage (' Killing parent ');
  217. Exit ();
  218. } else {
  219. Sub-process of fork
  220. $this->_ischildren = true;
  221. $this->_pid = Posix_getpid ();
  222. return true;
  223. }
  224. }
  225. /**
  226. * Sets identity of a daemon and returns result
  227. *
  228. * @return BOOL
  229. */
  230. Private Function _setidentity () {
  231. if (!posix_setgid ($this->groupid) | | |!posix_setuid ($this->userid))
  232. {
  233. $this->_logmessage (' Could not set identity ', self::D log_warning);
  234. return false;
  235. }
  236. Else
  237. {
  238. return true;
  239. }
  240. }
  241. /**
  242. * Signals Handler
  243. *
  244. * @access Public
  245. * @since 1.0
  246. * @return void
  247. */
  248. Public Function Sighandler ($sigNo) {
  249. Switch ($sigNo)
  250. {
  251. Case SIGTERM://Shutdown
  252. $this->_logmessage (' Shutdown signal ');
  253. Exit ();
  254. Break
  255. Case SIGCHLD://Halt
  256. $this->_logmessage (' Halt signal ');
  257. while (Pcntl_waitpid ( -1, $status, Wnohang) > 0);
  258. Break
  259. Case SIGUSR1://user-defined
  260. $this->_logmessage (' user-defined signal 1 ');
  261. $this->_sighandleruser1 ();
  262. Break
  263. Case SIGUSR2://user-defined
  264. $this->_logmessage (' user-defined signal 2 ');
  265. $this->_sighandleruser2 ();
  266. Break
  267. }
  268. }
  269. /**
  270. * Signals HANDLER:USR1
  271. * Primarily used to periodically clean up DNS parsing records of cached domain names in each process
  272. *
  273. * @return void
  274. */
  275. protected function _sighandleruser1 () {
  276. Apc_clear_cache (' user ');
  277. }
  278. /**
  279. * Signals HANDLER:USR2
  280. * For writing heartbeat package files
  281. *
  282. * @return void
  283. */
  284. protected function _sighandleruser2 () {
  285. $this->_initprocesslocation ();
  286. File_put_contents ($this->processheartlocation, Time ());
  287. return true;
  288. }
  289. /**
  290. * Releases daemon pid file
  291. * This method was called on exit (destructor like)
  292. *
  293. * @return void
  294. */
  295. Public Function Releasedaemon () {
  296. if ($this->_ischildren && is_file ($this->pidfilelocation)) {
  297. $this->_logmessage (' releasing Daemon ');
  298. Unlink ($this->pidfilelocation);
  299. }
  300. }
  301. /**
  302. * Writeprocess
  303. * Write the current process information to the monitoring log, another script will scan the monitoring log data send signal, if not responding, restart the process
  304. *
  305. * @return void
  306. */
  307. Public Function writeprocess () {
  308. Initialize proc
  309. $this->_initprocesslocation ();
  310. $command = Trim (implode (' ', $_server[' argv '));
  311. Specify the directory for the process
  312. $processDir = $this->processlocation. '/' . $this->_pid;
  313. $processCmdFile = $processDir. '/cmd ';
  314. $processPwdFile = $processDir. '/pwd ';
  315. directory where all processes are located
  316. if (!is_dir ($this->processlocation)) {
  317. mkdir ($this->processlocation, 0777);
  318. chmod ($processDir, 0777);
  319. }
  320. Querying for Duplicate process records
  321. $pDirObject = Dir ($this->processlocation);
  322. while ($pDirObject && ($pid = $pDirObject->read ())!== false) {
  323. if ($pid = = '. ' | | $pid = = ' ... ' | | intval ($PID)! = $pid) {
  324. Continue
  325. }
  326. $pDir = $this->processlocation. '/' . $pid;
  327. $pCmdFile = $pDir. '/cmd ';
  328. $pPwdFile = $pDir. '/pwd ';
  329. $pHeartFile = $pDir. '/heart ';
  330. Process that initiates the same parameters according to the cmd check
  331. if (Is_file ($pCmdFile) && trim (file_get_contents ($pCmdFile)) = = $command) {
  332. Unlink ($pCmdFile);
  333. Unlink ($pPwdFile);
  334. Unlink ($pHeartFile);
  335. Delete Directory has cache
  336. Usleep (1000);
  337. RmDir ($pDir);
  338. }
  339. }
  340. New Process Directory
  341. if (!is_dir ($processDir)) {
  342. mkdir ($processDir, 0777);
  343. chmod ($processDir, 0777);
  344. }
  345. Write Command Arguments
  346. File_put_contents ($processCmdFile, $command);
  347. File_put_contents ($processPwdFile, $_server[' PWD ');
  348. Write file has cache
  349. Usleep (1000);
  350. return true;
  351. }
  352. /**
  353. * _initprocesslocation
  354. * Initialization
  355. *
  356. * @return void
  357. */
  358. protected function _initprocesslocation () {
  359. $this->processlocation = Root_path. '/app/data/proc ';
  360. $this->processheartlocation = $this->processlocation. '/' . $this->_pid. '/heart ';
  361. }
  362. }
Copy Code
  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.