Exemple de démon PHP

12/03/2005

Par Stephane Eyskens (Autres articles)
 

Ce court article va vous expliquer comment exécuter un "démon" php en tant que service windows.


1. Introduction
2. Téléchargement de l'extension
3. Petit exemple de démon
4. Fonctionnement
5. Téléchargement


1. Introduction


Le but de cet article est de vous montrer comment faire tourner un script PHP5 en tant que service Windows. Ce besoin s'avère parfois nécessaire lorsque vous disposez de scripts "démons" qui doivent s'exécuter inconditionnellement pour effectuer leurs opérations. Sous linux ou unix, il est assez simple de mettre en oeuvre de tels démons et de les faire démarrer au boot de la machine. Sous windows par contre, c'est une autre paire de manches. Wez Furlong a créé l'extension win32service.dll qui permet de faire cela. Nous allons donc voir comment la mettre en oeuvre à l'aide d'un petit exemple.


2. Téléchargement de l'extension


Avant de télécharger l'extension, assurez-vous que vous disposez d'une version de PHP5 suffisamment récente pour être compatible avec celle-ci. Pour l'exemple qui vous sera expliqué en section 3, j'ai utilisé la version 5.0.3.3 disponible ici et l'extension proprement dite est disponible ici

Si vous ne savez pas comment installer PHP5, référez-vous à d'autres tutoriels de ce site décrivant les étapes à suivre. Pour installer l'extension, vous devez simplement télécharger le fichier et le sauvegarder dans le répertoire "ext" de php, ce répertoire étant le répertoire par défaut pour les extensions. Si vous avez spécifié un autre répertoire dans php.ini via la directive extension_dir, placez-y votre extension.

Il est inutile de faire charger cette extension par Apache car les scripts de type démon seront exécutés via PHP-CLI. Vous ne devez donc pas modifier votre php.ini. Nous verrons comment charger l'extension dynamiquement directement dans le script.


3. Petit exemple de démon


Pour vous fournir un petit exemple, j'ai décidé de développer un petit démon qui effectue le backup d'une DB SQLite toutes les heures. Tous les commentaires utiles sont dans le script.

<?php define(TARGETDB,'c:/dvpactivedb.db'); define(BACKUPDB,'d:/dvpbackupdb.db'); define(LOGFILE,'c:/backupDaemon.log'); define(BACKUPINTERVAL,3600); define(ERR_CD1,'Impossible d\'ouvrir le fichier Log'); define(ERR_CD2,'La base de données à sauvegarder n\'a pu être trouvée'); define(ERR_CD3,'Impossible de copier la base de donnée'); class BackupDaemon { private $logFileRes=null; function __construct() { $this->startDaemon(); } private function startDaemon() { $x = win32_start_service_ctrl_dispatcher('PHP_BackupDB'); $sleepTime=1; $this->backupDB(); /* On commence par effectuer un backup directement */ /* La condition de cette boucle sert à vérifier qu'on a pas tenté de stopper le service dans le SCM. Il ne faut donc pas trop dormir trop longtemps(sleep) sous peine que l'utilisateur ne puisse stopper le service. */ while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message()) { if($sleepTime == BACKUPINTERVAL) { $sleepTime=1; $this->backupDB(); } sleep(1); $sleepTime++; } } private function backupDB() { if(!file_exists(TARGETDB)) { $this->handleError(ERR_CD2); } if(!(copy(TARGETDB,BACKUPDB))) { $this->handleError(ERR_CD3); } $this->logIt('Dernier backup effectué correctement:'.date('y/m/d h:i:s')); } private function logIt($msg) { if(!is_resource($this->logFileRes)) { $this->logFileRes=fopen(LOGFILE,'a+') or $this->handleError(); } fwrite($this->logFileRes,$msg."\r\n"); } private function handleError($err) { if($err != ERR_CD1) { $this->logIt($err); } $this->__destruct(); } function __destruct() { /* Si le fichier log a été correctement ouvert, on le ferme */ if(is_resource($this->logFileRes)) { fclose($this->logFileRes); } die(); } } /* On vérifie que l'extension est chargée, si elle ne l'est pas, on la charge*/ if(!extension_loaded('php_win32service')) { dl('php_win32service.dll') or die('Impossible de charger la librairie php_win32service.dll'); } /* On vérifie les paramètres passés au script */ if(isset($argv[1])) { $validParams=array('install','uninstall'); if(!in_array($argv[1],$validParams)) { die('Veuillez specifier install || uninstall comme premier parametre'); } if ($argv[1] == 'install') { /* Création du service dans le SCM (service control manager) La fonction win32_create_service crée le service dans le SCM. Le nom du service est donné en tant que premier paramètre, le label qu'il aura dans le SCM dans le second et le fichier qu'il devra lancer ainsi que l'argument run dans le 3ème paramètre. */ $createService = win32_create_service(array( 'service' => 'PHP_BackupDB', 'display' => 'Exemple de démon DVP', 'params' => __FILE__, )); if($createService !== true) { die('Impossible de créer le service!'); } else { die('Service cree avec succes'); } } else if ($argv[1] == 'uninstall') { /* win32_delete_service marque le service comme "disabled/désactivé" dans le SCM. */ $removeService = win32_delete_service('PHP_BackupDB2'); switch($removeService) { case 1060: die('Ce service n\'existe pas');break; case 1072: die('Ce service n\'a pu être supprimé, il est probablement actif ou corrompu!');break; case 0:die('Service supprime avec succes');break; default:die();break; } } } else { $daemon=new BackupDaemon(); } ?>
Lorsque vous aurez téléchargé ou recopié ce script, vous devez l'exécuter en ligne de commande comme suit pour installer le service:

Lorsque le service a été créé, vous pourrez dès lors le démarrer soit en exécutant
net start lenomdevotreservice
soit, en ouvrant l'interface graphique permettant de gérer les services, comme ceci:

et en cliquant sur démarrer/start


4. Fonctionnement


Grâce à cette nouvelle extension, il est désormais assez facile d'exécuter un script PHP5 en tant que service windows. A l'heure actuelle, il n'y a quasiment aucune documentation sur cette extension. Elle est assez basique et comprend peu de fonctions. Ces fonctions ont été utilisées dans le script donné en exemple.

L'utilisateur par défaut qui est "owner" du service est l'utilisateur system. La fonction win32_create_service permet de spécifier un autre utilisateur en lui passant 'user' => le_user comme paramètre. Ne perdez pas de vue lorsque vous créerez vos services qu'il faut toujours vérifier si le SCM envoie un signal d'interruption du service. Si vous faites un démon qui dort pendant 1h (sleep 3600), l'utilisateur ne pourra jamais stopper le service car le signal ne sera jamais intercepté par le script. La plateforme que j'ai utilisé pour tester cette extension est Windows XP pro service pack1.


5. Téléchargement


Vous pouvez télécharger ce script ici



Cet article est la propriété de www.developpez.com en tant qu'hebergeur ainsi que celle de Stephaneey en tant que redacteur, ce texte est donc protégé par le code de la propriété intellectuelle et est soumis à la réglementation en vigueur.
www.developpez.com ou son auteur se reserve le droit d'apporter des modifications sans préavis. Vous pouvez utiliser cet article comme bon vous semble, faire un lien depuis votre site Web, ou le copier en spécifiant l'auteur et la provenance (www.developpez.com) Le non respect de cette règle equivaudrait à faire une contrefaçon. La responsabilité de www.developpez.com, de l'un de ses membres, ou de la direction ne pourra etre engagé en cas de destruction partielle ou totale des données ou de l'architecture système ou logicielle inhérente à l'utilisation des ses logiciels.
Les logiciels decrits ici sont la propriété de leurs auteurs respectifs.
Vos questions techniques : forum d'entraide PHP - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Hébergement - Participez - Copyright © 2000-2010 www.developpez.com - Legal informations.