PHP Classes

System Daemon: Start and stop daemon scripts in PHP

Recommend this page to a friend!
     
  Info   Example   View files Files   Install with Composer Install with Composer   Download Download   Reputation   Support forum   Blog    
Ratings Unique User Downloads Download Rankings
Not enough user ratingsTotal: 288 All time: 7,524 This week: 59Up
Version License PHP version Categories
systemdaemon 1.0.2MIT/X Consortium ...5PHP 5, Console
Description 

Author

This package can start and stop daemon scripts in PHP.

It provides a base class that can be extended to handle several events about a deamon process using the extension class functions to override the handling of those events.

Currently it can handle events like those of starting of the daemon, system signals, etc..

The class will handle console parameters that will tell the daemon to start, stop, or kill existing daemon processes.

Innovation Award
PHP Programming Innovation award winner
September 2017
Winner
Daemons are programs that can run on the background to execute a kind of service that must be running continuously.

Usually only one instance of a daemon program can be run at a given time.

This class can be used as base of daemon programs written in PHP. It can process parameters passed via the command line to execute actions typical of daemon programs like starting daemons, stopping daemons or handling signals for killing daemon processes that may be running.

Manuel Lemos
Picture of Sergey Vanyushin
  Performance   Level  
Name: Sergey Vanyushin is available for providing paid consulting. Contact Sergey Vanyushin .
Classes: 15 packages by
Country: Russian Federation Russian Federation
Age: 28
All time rank: 57216 in Russian Federation Russian Federation
Week rank: 23 Up4 in Russian Federation Russian Federation Up
Innovation award
Innovation award
Nominee: 15x

Winner: 2x

Example

#!/usr/bin/env php
<?php
require_once __DIR__.'/../vendor/autoload.php';

use
wapmorgan\SystemDaemon\AbstractDaemon;
use
wapmorgan\SystemDaemon\DaemonManager;

$daemon = new AbstractDaemon(AbstractDaemon::NORMAL, 1);
$daemon->name = 'example';
$daemon->setLogger(AbstractDaemon::FILES_DEBUG);

(new
DaemonManager($daemon))->handleConsole($argc, $argv);


Details

SystemDaemon

Simple base for system daemons.

Composer package Latest Stable Version Latest Unstable Version License

Why do you need SystemDaemon?

  1. You want to create a daemon (the process that works in the background) and be able to manage it
  2. You want to get rid of unnecessary dependencies in the project
  3. You do not want to manually make a base for such a daemon

If all three items are valid for your situation, SystemDaemon will satisfy all your needs.

What you need to create your own daemon:

  1. Create a class that inherits `AbstractDaemon` and implement methods for working in the background
  2. Run an instance of this class or use `DaemonManager`

In fact, you can avoid creating a new class and use the base class to create a daemon to see it's work. Also we will use DaemonManager not to write the code for processing user commands for starting / stopping the daemon.

DaemonManager processes input in the command line and runs the necessary methods of the AbstractDaemon class to start, stop, check the status of the daemon and etc.

The simplest daemon that simply outputs simple messages to the log:

// adjust here path to composer autoloader!
require_once __DIR__.'/../vendor/autoload.php';

use wapmorgan\SystemDaemon\AbstractDaemon;
use wapmorgan\SystemDaemon\DaemonManager;

$daemon = new AbstractDaemon();
$daemon->name = 'example';
$daemon->setLogger(AbstractDaemon::FILES);

(new DaemonManager($daemon))->handleConsole($argc, $argv);

Save this file as daemon and run it using php:

$ php daemon

You will see a simple help listing the valid commands for starting / stopping / checking the status of the job:

Manager for daemon "example". Available operations: daemon (start | status | stop | restart | kill)

To start the daemon, simply call the same script with the start command. If successful, the process ID after the start will be displayed, which can be used to view the statistics of this process.

$ php daemon start
Successfully started. Pid is 8868

_Since logging was enabled, you can open the file /tmp/daemon-example.log (or /var/log/daemon-example.log if permissions are allowed) and see what the daemon writes:_

2017-07-28 23:56:40 info: This is a informing message. Reimplement wapmorgan\SystemDaemon\AbstractDaemon::onStart() method to do real work.
2017-07-28 23:56:42 info: This is a informing message. Reimplement wapmorgan\SystemDaemon\AbstractDaemon::onStart() method to do real work.
2017-07-28 23:56:44 info: This is a informing message. Reimplement wapmorgan\SystemDaemon\AbstractDaemon::onStart() method to do real work.
...

This is a standard stub message that is written to the log, unless the standard daemon methods in which all the work is done have been redefined.

You can not use DaemonManager, if it is not necessary. Then, to control the daemon, use the following methods of AbstractDaemon:

  • `start()`: returns process ID of started daemon.
  • `stop()`: returns `true` if daemon stopped, `false` if not, `null` if was not running. This operation is preferred over `kill()` because you can catch this action in daemon and correctly finish it.
  • `kill()`: returns `true` if daemon stopped, `false` if not, `null` if was not running. This operation performs system kill, which just terminates script.
  • `getStatus()`: return `false` if daemon is not running, `stdClass` object with daemon information if running.

All these methods can throw exceptions if something goes wrong (for example, there is not enough permissions to remove the lock file, if the unprivileged user is trying to stop the daemon started by root), so take care of handling such situations.

To resume: the main features that AbstractDaemon provides: 1. Start the daemon in the background. The ban on running multiple copies of the daemon using a lock file. 2. Create a log file and write messages to it. 3. The daemon can be of two types: a normal daemon (in which the onStart() method is started once and all the work is done) and a daemon waking up at certain intervals (called "ticks") and executing the onTick() method.

Types of daemons

The created daemon can work in two modes:

  1. Normal. When one method is started and it processes some external data (for example, listening on a socket). This mode is used by default. To create your daemon, you need to override the `onStart()` method, which will be called when the daemon starts. For example, this:

    class MyDaemon extends AbstractDaemon
    {
        protected function onStart()
        {
            // here's your daemon's code
        }
    }
    
  2. Ticking. When a daemon wakes up at regular intervals, it gets some information, does its job and falls asleep until the next "tick". To use this mode, you need to transfer the `AbstractDaemon::TICKABLE` value and the time that the daemon will wake up (in seconds) when creating a class instance. For example. So:

    $daemon = new MyDaemon(AbstractDaemon::TICKABLE, 2); // this daemon will "tick" every 2 seconds
    

    To create such a daemon, you need to override the `onTick()` method, in which specify operations of the daemon within one tick:

    class MyDaemon extends AbstractDaemon { protected function onTick() { // here's your daemon's code on every tick } }

    ## Stopping Stop processing for each type of its own:

  3. A normal daemon processes a stop event (called by the `stop()` method) in the `handleStop()` method. You can override this method and make closing some sockets or setting a completion flag there, and in `onStart()` do a check: if the flag was set, finish the data processing and exit the method. In the base class, `handleStop()` sets the `$running` property of the daemon to false, so you can just check sometimes if that value is set there and shut down. For example, you can do this:

    class MyDaemon extends AbstractDaemon
    {
        protected $fp;
    
        protected function handleStop()
        {
            fclose($this->fp);
            $this->fp = null;
        }
    
        protected function onStart()
        {
            $this->fp = fopen('example-file', 'r');
            while (is_resource($this->fp)) {
                // data processing
            }
        }
    }
    
  4. The ticking daemon is easier to use: it continues its ticks until the stop command comes. Thus, you do not need to manually process this operation. The daemon will end after the tick, at the time of processing of which this command came.

Other signals

You have the ability to process other signals sent by the kill command. At the moment, it is possible to process two signals, which can be used as buffer reset commands, clearing the cache, or something else. These commands are: SIGUSR1 and SIGUSR2. To process them in the daemon, reimplement the onSigUsr1() and onSigUsr2() methods, respectively.

To reboot the daemon settings using the USR1 command, you can implement such a daemon:

class MyDaemon extends AbstractDaemon
{
    protected $config;
    
    protected function onSigUsr1()
    {
        $this->loadConfiguration();
    }
    
    protected function onStart()
    {
        $this->loadConfiguration();
        // ...
    }
    
    protected function loadConfiguration()
    {
        $this->config = json_decode(file_get_contents(__DIR__.'/config.json'));
    }
}

Logging

You can use message logging. To enable logging, you must call the setLogger($logger) method after creating the daemon object. Two types of logging are supported: 1. Logging to syslog. Example of use:

$daemon = new AbstractDaemon();
$daemon->setLogger(AbstractDaemon::SYSLOG);

  1. Logging to a separate file. To enable logging in a separate file (/var/log/daemon-daemon name.log, if permissions allow, or /tmp/daemon-name.log):
    $daemon = new AbstractDaemon();
    $daemon->setLogger(AbstractDaemon::FILES);
    
  2. Logging to a terminal. Daemon just prints all log messages right on the terminal:
    $daemon = new AbstractDaemon();
    $daemon->setLogger(AbstractDaemon::TERMINAL);
    

To send messages to the log in the daemon use log($level, $message) method, where $level is one of the predefined message severity levels and $message messages.

Predefined levels of importance are: - AbstractDaemon::ERROR - AbstractDaemon::WARNING - AbstractDaemon::NOTICE - AbstractDaemon::INFO - AbstractDaemon::DEBUG


  Files folder image Files (9)  
File Role Description
Files folder imagebin (1 file)
Files folder imagesrc (2 files, 1 directory)
Plain text file composer.json Data Auxiliary data
Plain text file LICENSE Lic. License text
Plain text file README.md Doc. Documentation

  Files folder image Files (9)  /  bin  
File Role Description
  Plain text file example Example Example script

  Files folder image Files (9)  /  src  
File Role Description
Files folder imageLoggers (3 files)
  Plain text file AbstractDaemon.php Class Class source
  Plain text file DaemonManager.php Class Class source

  Files folder image Files (9)  /  src  /  Loggers  
File Role Description
  Plain text file FilesLogger.php Class Class source
  Plain text file SyslogLogger.php Class Class source
  Plain text file TerminalLogger.php Class Class source

The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page.
Install with Composer Install with Composer
 Version Control Unique User Downloads Download Rankings  
 100%
Total:288
This week:0
All time:7,524
This week:59Up