Php daemon

De The Linux Craftsman
Aller à la navigation Aller à la recherche

Introduction

Définition

Un daemon [...], parfois traduit par démon, désigne un type de programme informatique, un processus ou un ensemble de processus qui s'exécute en arrière-plan plutôt que sous le contrôle direct d'un utilisateur. Wikipedia

Principe

Pour qu'un processus soit considéré comme un démon, il faut :

  • qu'il puisse répondre au signaux du système ;
  • qu'il continue son exécution avec ou sans contrôle utilisateur.

Mise en place

Réception des signaux système

Nous allons créer une classe serveur qui va répondre aux interruptions envoyées par le système. Celles qui vont nous intéresser sont :

  • SIGINT : signal d’interruption déclenché par ctrl+c;
  • SIGTERM : signal de terminaison déclenché par la commande kill;
  • SIGCHLD : signal utilisé pour gérer les processus fils (fork)
  • SIGHUP : signal utilisé pour redémarrer un processus;

Nous allons créer une classe abstraite Daemon qui va nous servir de base pour répondre aux signaux :

<?php
abstract class Daemon {
	protected $name;
	private $isRunning = true;
	/**
	 * Classe permettant de répondre aux signaux système
	 * @param string $name
	 * Le nom de la classe
	 */
	protected function __construct($name) {
		$this->name = $name;
		// Permet au script PHP de s'éxécuter indéfiniment
		set_time_limit ( 0 );
		$this->registerSignals ();
	}
	/**
	 * Fonction qui permet l'enregistrement des signaux
	 */
	private function registerSignals() {
		declare ( ticks = 1 )
			;
		pcntl_signal ( SIGTERM, array (
				'Daemon',
				'handleSignal' 
		) );
		pcntl_signal ( SIGINT, array (
				'Daemon',
				'handleSignal' 
		) );
		pcntl_signal ( SIGCHLD, array (
				'Daemon',
				'handleSignal' 
		) );
	}
	/**
	 * Fonction qui s'occupe de la gestion des signaux
	 *
	 * @param string $signal
	 */
	private function handleSignal($signal) {
		if ($signal == SIGTERM || $signal == SIGTERM) {
			// Gestion de l'extinction
			$this->stop ();
		} else if ($sig == SIGHUP) {
			// Gestion du redémarrage
			$this->onStop();
			$this->onStart();
		} else if ($sig == SIGCHLD) {
			// Gestion des processus fils
			pcntl_waitpid ( - 1, $status, WNOHANG );
		} else {
			// Gestion des autres signaux
			$this->handleOtherSignals ();
		}
	}
	/**
	 * Fonction qui va permettre d'exécuter 
	 * indéfiniment la function ''run''
	 */
	protected function start(){
		$this->onStart();
		while ($this->isRunning){
			$this->run();
		}
	}
	/**
	 * Fonction exécutée indéfiniment
	 */
	protected abstract function run();
	/**
	 * Fonction exécutée une fois au démarrage du démon
	 */
	protected abstract function onStart();
	/**
	 * Fonction exécutée une fois à l'arrêt du démon
	 */
	protected abstract function onStop();
	/**
	 * Fonction laissée pour la gestion des autres signaux
	 */
	protected abstract function handleOtherSignals();
}

?>

La classe Daemon ne peut pas être instanciée car elle est abstraite ce qui permet de définir les méthodes abstraites onStart, onStop, run et handleOtherSignals. Le code de ces méthodes est spécifique à chaque démon et c'est pour cela que l'utilisateur qui va étendre la classe Daemon devra les surcharger.

Cela nous permet dans la classe Daemon de seulement coder le comportement du démon et non ce qu'il fait.

Implémentation