Php daemon
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 {
public $name;
private $isRunning = true;
/**
* Classe permettant de répondre aux signaux système
* @param string $name
* Le nom de la classe
*/
public 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) {
// Géstion du redémarrage
$this->onStop();
$this->onStart();
} else if ($sig == SIGCHLD) {
// Géstion des retour des processus fils
pcntl_waitpid ( - 1, $status, WNOHANG );
} else {
echo "Reçu le signal " . $sig . "\n";
$this->stop ();
break;
// gestion des autres signaux
}
}
/**
* Fonction qui va permettre d'exécuter
* indéfiniment la function ''run''
*/
public 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.