Share The PHP daemon class

Source: Internet
Author: User
This article mainly introduces the PHP Daemon class, which is a special process running in the background. It is independent of the control terminal and periodically executes a task or waits to process some events. Daemon is a very useful process. Php can also implement Daemon class implemented by PHP. You can implement a queue or a scheduled task that is out of crontab on the server.
When used, it inherits from this class and overwrites the _ doTask method, which is initialized and executed through main.

<? Php class Daemon {const DLOG_TO_CONSOLE = 1; const DLOG_NOTICE = 2; const DLOG_WARNING = 4; const DLOG_ERROR = 8; const DLOG_CRITICAL = 16; const DAPC_PATH = '/tmp/done '; /*** User ID ** @ var int */public $ userID = 65534; // nobody/*** Group ID ** @ var integer */public $ groupID = 65533; // nobody/*** Terminate daemon when set identity failure? ** @ Var bool * @ since 1.0.3 */public $ requireSetIdentity = false; /*** Path to PID file ** @ var string * @ since 1.0.1 */public $ pidFileLocation = '/tmp/daemon. pid ';/*** processLocation * process information record directory ** @ var string */public $ processLocation = ''; /*** processHeartLocation * process heartpackage file ** @ var string */public $ processHeartLocation = ''; /*** Home path ** @ var string * @ since 1.0 */public $ h OmePath = '/';/*** Current process ID ** @ var int * @ since 1.0 */protected $ _ pid = 0; /*** Is this process a children ** @ var boolean * @ since 1.0 */protected $ _ isChildren = false; /*** Is daemon running ** @ var boolean * @ since 1.0 */protected $ _ isRunning = false; /*** Constructor *** @ return void */public function _ construct () {error_reporting (0); set_time_limit (0); ob_implicit_flu Sh (); register_shutdown_function (array (& $ this, 'releasedaemon');}/*** start process *** @ return bool */public function main () {$ this-> _ logMessage ('starting daemon'); if (! $ This-> _ daemonize () {$ this-> _ logMessage ('could not start daemon', self: DLOG_ERROR); return false ;} $ this-> _ logMessage ('running... '); $ this-> _ isRunning = true; while ($ this-> _ isRunning) {$ this-> _ doTask ();} return true ;} /*** stop the process ** @ return void */public function stop () {$ this-> _ logMessage ('stoping daemon '); $ this-> _ isRunning = false;}/*** Do task ** @ return void */protected function _ DoTask () {// override this method}/*** _ logMessage * Record log ** @ param string message * @ param integer level * @ return void */protected function _ logMessage ($ msg, $ level = self: DLOG_NOTICE) {// override this method}/*** Daemonize ** Several rules or characteristics that most daemons possess: * 1) check is daemon already running * 2) Fork child process * 3) Sets identity * 4) Make current proces S a session laeder * 5) Write process ID to file * 6) Change home path * 7) umask (0) ** @ access private * @ since 1.0 * @ return void */private function _ daemonize () {ob_end_flush (); if ($ this-> _ isDaemonRunning ()) {// Deamon is already running. exiting return false;} if (! $ This-> _ fork () {// Coudn't fork. Exiting. return false;} if (! $ This-> _ setIdentity () & $ this-> requireSetIdentity) {// Required identity set failed. Exiting return false;} if (! Posix_setsid () {$ this-> _ logMessage ('could not make the current process a session leader ', self: DLOG_ERROR); return false;} if (! $ Fp = fopen ($ this-> pidFileLocation, 'w') {$ this-> _ logMessage ('could not write to PID file', self: DLOG_ERROR ); return false;} else {fputs ($ fp, $ this-> _ pid); fclose ($ fp);} // write monitoring logs $ this-> writeProcess (); chdir ($ this-> homePath); umask (0); declare (ticks = 1); pcntl_signal (SIGCHLD, array (& $ this, 'sighandler ')); pcntl_signal (SIGTERM, array (& $ this, 'sighandler'); pcntl_signal (SIGUSR1, array (& $ this, 'Sighandler'); pcntl_signal (SIGUSR2, array (& $ this, 'sighandler'); return true ;} /*** Cheks is daemon already running ** @ return bool */private function _ isDaemonRunning () {$ oldPid = file_get_contents ($ this-> pidFileLocation); if ($ oldPid! = False & posix_kill (trim ($ oldPid), 0) {$ this-> _ logMessage ('daemon already running with PID :'. $ oldPid, (self: DLOG_TO_CONSOLE | self: DLOG_ERROR); return true ;}else {return false ;}} /*** Forks process *** @ return bool */private function _ fork () {$ this-> _ logMessage ('Forking... '); $ pid = pcntl_fork (); if ($ pid =-1) {// error $ this-> _ logMessage ('could not fork', self :: DLOG_ERROR); return False;} elseif ($ pid) {// parent process $ this-> _ logMessage ('killing parent'); exit ();} else {// fork sub-process $ this-> _ isChildren = true; $ this-> _ pid = posix_getpid (); return true ;}} /*** Sets identity of a daemon and returns result *** @ return bool */private function _ setIdentity () {if (! Posix_setgid ($ this-> groupID) |! Posix_setuid ($ this-> userID) {$ this-> _ logMessage ('could not set identifi', self: DLOG_WARNING); return false ;} else {return true;}/*** Signals handler ** @ access public * @ since 1.0 * @ return void */public function sigHandler ($ sigNo) {switch ($ sigNo) {case SIGTERM: // Shutdown $ this-> _ logMessage ('shutdown signal '); exit (); break; case SIGCHLD: // Halt $ this-> _ logMessage ('halt signal '); While (pcntl_waitpid (-1, $ status, WNOHANG)> 0); break; case SIGUSR1: // User-defined $ this-> _ logMessage ('User-defined signal 1'); $ this-> _ sigHandlerUser1 (); break; case SIGUSR2: // User-defined $ this-> _ logMessage ('User-defined signal 2'); $ this-> _ sigHandlerUser2 (); break ;}} /*** Signals handler: USR1 * is mainly used to regularly clear the cached dns resolution records of domain names in each process ** @ return void */protected function _ sigHandlerUser1 () {apc_c Lear_cache ('user');}/*** Signals handler: USR2 * used to write the heartbeat package file ** @ return void */protected function _ sigHandlerUser2 () {$ this-> _ initProcessLocation (); file_put_contents ($ this-> processHeartLocation, time (); return true ;} /*** Releases daemon pid file * This method is called on exit (destructor like) ** @ return void */public function releaseDaemon () {if ($ this-> _ isChildren & is_file ($ this-> PidFileLocation) {$ this-> _ logMessage ('releasing daemon'); unlink ($ this-> pidFileLocation );}} /*** writeProcess ** writes information about the current process to the monitoring log. The script also scans the data sending signals of the monitoring log, if no response is received, restart the process ** @ return void */public function writeProcess () {// initialize proc $ this-> _ initProcessLocation (); $ command = trim (implode ('', $ _ SERVER ['argv']); // specify the process directory $ processDir = $ this-> processLocation. '/'. $ this-> _ pid; $ processCmdFile = $ proc EssDir. '/cmd'; $ processPwdFile = $ processDir.'/pwd'; // if (! Is_dir ($ this-> processLocation) {mkdir ($ this-> processLocation, 0777); chmod ($ processDir, 0777 );} // query duplicate process records $ pDirObject = dir ($ this-> processLocation); while ($ pDirObject & ($ pid = $ pDirObject-> read ())! = False) {if ($ pid = '.' | $ pid = '..' | intval ($ pid )! = $ Pid) {continue;} $ pDir = $ this-> processLocation. '/'. $ pid; $ pCmdFile = $ pDir. '/cmd'; $ pPwdFile = $ pDir. '/pwd'; $ pHeartFile = $ pDir. '/heart'; // run the cmd check to start the process with the same parameters if (is_file ($ pCmdFile) & trim (file_get_contents ($ pCmdFile) ==$ command) {unlink ($ pCmdFile); unlink ($ pPwdFile); unlink ($ pHeartFile); // delete the cache usleep (1000); rmdir ($ pDir );}} // New process directory if (! Is_dir ($ processDir) {mkdir ($ processDir, 0777); chmod ($ processDir, 0777) ;}// write command parameter file_put_contents ($ processCmdFile, $ command ); file_put_contents ($ processPwdFile, $ _ SERVER ['pwd']); // The written file has the cache usleep (1000); return true ;} /*** _ initProcessLocation * initialization ** @ return void */protected function _ initProcessLocation () {$ this-> processLocation = ROOT_PATH. '/app/data/proc'; $ this-> processHeartLocation = $ this-> processLocation. '/'. $ this-> _ pid. '/heart ';}}

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.