Au risque d'en décevoir certain, dans la majorité des cas, je pense que la réponse est négative.
Si j'ai écris un certain nombre de démons, c'était pour répondre à des besoins strictement personnels, et ceci pour deux raisons.
Tout d'abord, j'avais envie de m'amuser, et le challenge me semblait à chaque fois intéressant.
C'est d'ailleurs pour cette raison que le gestionnaire de fenêtre que j'utilise sous FreeBSD utilise des démons écrit en PHP pour interagir avec l'utilisateur.
Ensuite, je n'ai jamais rencontré dans mon contexte professionnelle un cas de figure qui nécessité la mise en œuvre d'un démon.
En effet, dans tous les cas, un script régie via l'utilitaire cron
s'est révélé bien plus adapté, pour plusieurs raisons.
Tout d'abord, indépendamment de son écriture, un démon est bien plus complexe à mettre en œuvre qu'un script déclenché à intervalle régulier par cron
.
Il est en effet nécessaire de faire en sorte que le démon se lance au démarrage (ou au redémarrage en cas de plantage) du serveur physique, et qu'il puisse également être arrêté ou redemarré.
Or, bien souvent, cela passe par l'écriture de un ou plusieurs scripts, souvent écrit en sh, et dont la structure est bien souvent spécifiques au système d'exploitation.
De fait, la portabilité de ces scripts, et donc du démon qu'ils gèrent, est donc problématique.
Avec un script dirigé par cron
, ce problème n'existe pas, puisque cet utilitaire est disponible sur tout les UNIX, et que de plus son fonctionnement est identique indépendamment du système d'exploitation.
Autre argument en faveur de l'utilisation de cron
, ce dernier avertira l'administrateur de la machine si jamais le script rencontre un problème lors de son exécution, puisqu'il capture la sortie standard et la sortie d'erreur des scripts qu'il exécute et envoie le courrier électronique correspondant si le script exécuté a écrit sur l'une ou l'autre.
Enfin, si PHP en lui-même n'a pas de fuites de mémoire significative, ce n'est pas forcément le cas des extensions qu'un démon peut être amené à mettre en œuvre. Si cela n'est pas un problème avec cron
, puisque le script est exécuté à intervalle régulier qu'en conséquence, les ressources mémoires qu'il consomme seront forcément libérées, ce n'est pas le cas avec un démon, qui par définition est destiné à tourner en permanence.
Donc, si le démon se révèle avoir des fuites de mémoire, dans le meilleur des cas, il atteindra la limite de mémoire autorité par la configuration de PHP et s'arrêtera de lui-même, et dans le pire des cas, il finira par consommer l'intégralité de la RAM disponible, compromettant ainsi le bon fonctionnement du serveur.
Enfin, changer la configuration d'un démon nécessite de pouvoir soit lui faire relire sa configuration dynamiquement, soit de l'arrêter et de le redémarrer.
Dans le cas d'une solution basée sur cron
, cela n'est pas nécessaire, puisque le script peut aller lire sa configuration lors de chaque démarrage.
Il suffit donc de modifier le fichier de configuration pour que les nouveaux paramètres soient automatiquement pris en compte, alors que dans le cas du démon, il faudra en plus demander au démon de relire sa configuration, soit l'arrêter et le redémarrer.
Bref, cron
est une solution plus simple et plus fiable techniquement, qui ne risque pas d'altérer le bon fonctionnement du serveur, et qui plus facile à gérer au quotidien.
Cela ne veut cependant pas dire que la solution du démon est à rejeter systématiquement.
Dans certain cas, elle est même incontournable, comme par exemple ceux ou la ou les tâches doivent être exécutées non pas à intervalle régulier, mais en fonction d'un événement ou bien lorsqu'il faut exécuter ces tâches le plus rapidement possible ou avec une granularité inférieure à la minute.
Il faut cependant l'utiliser en ayant bien conscience de tout ce qu'elle implique en terme de contraintes, et surtout que PHP n'est pas le langage le plus adapté pour cela, même s'il est parfaitement outillé pour le faire.
28 réactions
1 De Guillaume Gagnaire - 05/05/2011, 22:27
Bonjour,
Sous Windows, il n'y a pas crontab, donc si nous voulons faire un système multi-os (je pense par exemple à un CMS qui doit tourner sous Windows Server), il faut en reprendre le fonctionnement.
Cependant, à cause de fuites de mémoires de PHP, nous ne pouvons pas, dans un domaine professionnel, laisser tourner en deamon en tâche de fond. Par contre, à la fin du script, faire en sorte qu'il se relance automatiquement, ce qui nettoiera la mémoire
2 De mageekguy - 05/05/2011, 22:29
@Guillaume Gagnaire : N'ayant jamais développé sous WIndows et n'en ayant qu'une connaissance uniquement , je n'ai pas abordé le sujet dans le billet.
Merci donc d'avoir apporté ces éclaircissements (il me semblait cependant qu'il était possible de créer des services sous Windows, équivalent des démons UNIX).
3 De Da Scritch - 05/05/2011, 22:33
Écrire un démon, c'est effectivement écrire un programme qui tourne en continu et non pas au coup par coup. Et c'est là que l'on voit si on a une réelle maîtrise du langage et surtout une immense rigueur d'écriture : construire/détruire , déclarer/dédéclarer , monter/démonter , etc...
Car l'immense différence du PHP sur le C ou les autres langages, c'est ses petites facilités (transtypage, décla implicite, etc...) qui peuvent très vite mener à effectivement de grosses fuites de mémoire.
Je pense qu'au contraire, l'exercice est incontournable pour savoir si on est sérieux.
Après, les questions de connaître comment l'OS tourne derrière, c'est un minimum. Au bout d'un certain moment, il et inenvisageable de coder un gros projet web en php, perl, ruby, etc... sur un OS qui n'est pas un Unix/Linux/BSD . Les serveurs tournent plus souvent sur une Debian qu'une Windows, donc ... on ne code pas sous Windows.
Ou alors, on méconnais totalement comment fonctionne ses serveurs.
Et là, c'est très génant.
4 De Damien - 05/05/2011, 22:35
"[...] ces tâches le plus rapidement possible ou avec une granularité inférieure à la minute."
tout dépend du script, mais je sais pas ce qui est mieux, lancer un script PHP toutes les minutes ou avoir un démon qui réagit aux évènements ? sinon pour le reste je suis entièrement d'accord.
5 De mageekguy - 05/05/2011, 22:35
@Da Scritch : Les fuites de mémoire de PHP n'ont rien à voir avec ce que tu décris.
Le problème vient surtout de la gestion de référence de PHP, qui selon les versions, pose des problèmes au garbage collector, ainsi que du code C de PHP ou de ses extensions, qui n'est pas forcément écrit correctement.
6 De gandhu - 05/05/2011, 22:35
Sur windows, il y a le planificateur de taches qui permet d'utiliser PHP en CLI.
7 De ben - 05/05/2011, 23:21
@Guillaume Gagnaire : Sous windows tu n'as effectivement pas la cron tab, mais tu peux tout de même planifier des exécutions avec l'utilitaire des taches planifiées de Windows.
Si cela ne suffisait pas à faire ce que tu souhaites, il existe un extension PECL nommée win32_service (http://fr2.php.net/win32_service), qui permet de créer/transformer un script PHP en un service Windows assez simplement. L'avantage c'est que Windows peut se charger de relancer le service (rapidement) quand il plante. L’inconvenant c'est que je ne suis pas sur que cette extension soit très a jour, et qu'elle n'est pas forcément compilée pour toutes les versions de PHP. (mais ca se trouve sur internet)
8 De desfrenes - 06/05/2011, 00:18
Dans le genre à l'arrache, je suis le seul à faire tourner du php cli dans un screen pendant plusieurs mois ? ^_^
9 De mageekguy - 06/05/2011, 00:37
@desfrenes : <troll>Tu devrais utiliser tmux, parce que screen tue des chatons lorsqu'on l'utilise.</troll>
Sinon, c'est effectivement une autre solution, mais elle présente l'inconvénient qu'il n'y aura pas d'alerte en cas de problème, soit au niveau de screen, soit au niveau de ton script.
De plus, ça reste plus complexe à mettre en œuvre que
cron
, même si ce n'est pas la mère à boire.Et non, tu n'es pas le seul à faire cela.
J'utilise le combo
screentmux + PHP pour des scripts et pour des tâches non critiques et potentiellement assez longue, comme le nettoyage ou de l'analyse de code, de la génération de documentation, le remplissage de base de données lors de la mise en route d'un projet, etc.Cependant, ce n'est pas de mon point de vue une solution viable en environnement de production.
10 De loïc m. - 06/05/2011, 00:53
Auriez-vous des exemple où il est primordial qu'un script s’exécute immédiatement et qui justifierait l'utilisation des deamon PHP ?
travaillant dans le domaine de la télésurveillance, nous utilisons les tâches cron pour gérer des actions asynchrones qui peuvent attendre 'au maximum avant d'être exécutées
11 De Francis - 06/05/2011, 00:58
Si on parle d'asynchrone et de déléguer une partie de l'intelligence sur les pages web pour ne pas altérer leur déroulement, je pense que gearman est un très bon outil.
http://gearman.org/
12 De Ivan Enderlin - 06/05/2011, 07:03
Hey :-),
La mère ou la mer à boire ?
Tmux n'est pas assez stable contrairement à screen. Pour simplement lancer un script, screen est amplement suffisant.
Je réfléchis depuis un moment à faire des démons avec des sockets mais ce n'est pas simple. FastCGI fonctionnant uniquement en TCP, ce n'est pas facile de le désynchroniser. Une autre piste à suivre ?
13 De Paul - 06/05/2011, 07:10
C'est quand même dommage, qu'encore aujourd'hui PHP puisse encore avoir des fuites mémoires.
Certes pour la programmation de page web c'est pas grave, vu que généralement le temps d'execution d'un script est très rapide, mais ca fait pas très "pro".
En tout cas merci pour le billet.
14 De mageekguy - 06/05/2011, 08:57
@Ivan Enderlin : Tmux qui plante ??? Nous ne devons pas parler de la même chose.
Sinon, c'est une très mauvaise idée de lancer un démon autrement que par la CLI, à moins éventuellement de passer par un pcntl_exec() pour remplacer le code du fork par celui du script de ton choix, mais je ne suis même pas certain de cela, car j'ignore comment se comporte PHP vis à vis des descripteurs ouverts et des ressources consommées dans ce cas.
C'est à tester.
15 De mageekguy - 06/05/2011, 08:59
@Paul : Je répète : PHP en lui-même n'a pas de fuite de mémoire significative en utilisation conventionnelle.
J'ai des démons qui tournent avec 4 Mo depuis très longtemps, et ça ne bouge absolument pas.
S'il y en a, elles proviennent dans la grande majorité des cas d'extension tierce, comme Xdebug, par exemple (oui, c'est assez paradoxale).
16 De mageekguy - 06/05/2011, 09:02
@loïc m. :Votre commentaire étant incomplet, j'ai du mal à comprendre votre demande, mais sans trop y réfléchir, je vois assez peu de cas ou une réactivité proche du temps réel serait nécessaire, à part justement dans un contexte temps réel, comme de la synchronisation de données ou de la surveillance/monitoring,
17 De Amaury - 06/05/2011, 09:42
Un article presque entier à confronter les démons et la crontab... C'est un peu comme comparer HTTP et FTP : ça peut éventuellement être utilisé pour la même chose, mais l'écrasante majorité des utilisations est différente.
On écrit un démon pour réagir à des évènements, qui sont la plupart du temps des connexions entrantes. Faire un démon pour exécuter des tâches récurrentes, c'est inutile, il vaut effectivement mieux utiliser la crontab.
Sinon, parler des démons sans même évoquer inetd/xinetd, c'est fort. Tous les avantages que tu décris dans l'utilisation de la crontab (instanciation unique, donc fuites mémoire limitées, relecture du fichier de conf, ...) peuvent être mis en œuvre dans la création d'un démon en le basant sur inetd/xinetd. C'est une solution permettant d'écrire un démon très rapidement, car c'est alors juste un script CLI qui lit sur son entrée standard et qui écrit sur sa sortie standard. C'est juste limité en montée en charge, puisque chaque connexion entrante va instancier le chargement de l'interpréteur PHP complet. Cela reste très efficace pour la plupart des usages.
Autre chose, utiliser la crontab pour effectuer des tâches récurrentes impose souvent de mettre en place une solution de lock, pour éviter d'avoir plusieurs exécutions simultanées du même script. C'est une chose souvent oubliée par les développeurs qui codent leurs premiers scripts destinés à la crontab, ce qui génère fréquemment des bugs difficiles à reproduire.
18 De mageekguy - 06/05/2011, 09:46
@Amaury : Le billet a été rédigé en fonction des questions qui m'ont été posé, à savoir ce qui est le mieux entre un script en cron et un démon, et j'ai donc rédigé mon billet en conséquence, sans évoquer d'autres alternatives.
En ce qui concerne
inetd
/xinetd
, cette solution ne permet pas la mise en œuvre d'un démon, mais d'un script, un démon ne devant pas utiliser les entrées/sorties standards.La philosophie de ces outils est donc similaire à celle de
cron
, si ce n'est que le déclenchement sera alors événementiel et que cela pose effectivement des problèmes au niveau de la montée en charge et de la consommation des ressources.Concernant le lock, je ne l'ai pas précisé vu que mon billet est essentiellement fonctionnel, et non technique, et de plus, cela me semblait être évident.
D'ailleurs, tant que nous sommes dans la technique, je recommande de lancer un démon en PHP avec un interpréteur PHP compilé avec uniquement les fonctionnalités indispensables, ainsi qu'un php.ini spécifique.
19 De loïc m. - 06/05/2011, 09:53
pour corriger mon post précédent :
"travaillant dans le domaine de la télésurveillance, nous utilisons les tâches cron pour gérer des actions asynchrones qui peuvent attendre 1 minute au maximum avant d'être exécutées"
merci pour les exemples
20 De Mathieu ROBIN - 06/05/2011, 09:54
Sous Windows (pour avoir déjà eu à le faire - sous la contrainte, j'étais un pauvre stagiaire), il y a une solution usine à gaz :
Tâches planifiées Windows appelant l'exécution d'un script batch lui même faisant appel à une version windows de wget qui lui appellera les scripts php. 100% de chances que ça se plante au bout de quelques semaines pour une raison x ou y. Avec l'instabilité naturelle de windows en première ligne.
Pour le coup par contre, je n'ai jamais eu à faire de démon, ayant toujours pu coder une alternative avec cron. Et que c'est bon d'avoir cron sous Linux parce que bordel, qu'est-ce que le système de tâches planifiées sous windows est vraiment moisi...
21 De Amaury - 06/05/2011, 10:51
Justement, inetd/xinetd permet de "démonifier" un script. Quand tu dis qu'un démon ne doit pas utiliser ses entrées-sorties standard, tu veux parler des démons autonomes classiques, j'imagine. Cela n'a plus aucun sens avec inetd, dont le principe fondamental est d'encapsuler les programmes, d'être le démon à leur place, et de communiquer avec eux en utilisant les descripteurs standards.
Il est bien plus facile et rapide de développer un simple script qui utilise ses entrées-sorties standard que de coder un démon complet (socket, accept, fork, gestion des signaux). Au final, on obtient bien un démon qui écoute sur le port voulu et qui traite les connexions entrantes.
Évidemment, il faut que le script en question soit développé spécifiquement, avec cet usage en tête. Il ne faut pas prendre n'importe quel script CLI et le mettre dans inetd sans plus de réflexion.
Mais, sincèrement, pour la plupart des «petits démons», ceux qui servent pour des usages non critiques ou qui n'ont pas de trop grosses charges à supporter, c'est une solution très efficace.
22 De Yannick K. - 06/05/2011, 11:13
Perso j'ai toujours utiliser schtasks (http://www.microsoft.com/resources/...) comme alternative à crontab sous windows, je n'ai aucun soucis jusque là. Cependant je suis bien d'accord que l'utilisation de PHP pour l'écriture des démons n'est pas top comme solution. Matthieu Robin, le script était distant ?
23 De Bds023 - 06/05/2011, 12:20
@mageekguy
Pour avoir étudier récemment un problème de fuite mémoire PHP, j'ai découvert que ce bug(http://bugs.php.net/bug.php?id=3348...) est toujours présent en PHP et que le GC ne le corrige pas.
Par conséquent, je ne suis pas partisan des demons PHP. Ce n'est pas le langage adéquat. Par contre, il est tout à fait possible de faire en démon avec un langage approprié et qui appel des scripts PHP.
24 De Paul - 06/05/2011, 13:18
@Loïc m, tu cherches
1°) un exemple ou un démon est une meilleure solution à cron
ou alors
2°) un exemple ou un démon en __PHP__ est une meilleure solution à cron
25 De loïc m. - 06/05/2011, 17:10
@paul : deamon php vs. cron qui exécute une tâche php
où le deamon est plus intéressant que la tâche cron
26 De funkyproject - 09/05/2011, 11:25
bonjour, merci pour l'article.
J'utilise depuis un moment, en remplacement de cron, un script shell qui boucle sur un php -f ...
avec une commande WAIT du processus, pour interroger activemq. L'avantage est d'avoir une queue multiplateforme , un processus php unique , un limit_memory qui fait son travaille. C'est stable en production mais y a t'il une alternative à ma solution ?
27 De mageekguy - 09/05/2011, 21:35
@funkyproject : Si tu dois interroger activemq à intervalle régulier avec une granularité supérieure ou égale à la minute, un script en cron peut être une alternative.
Si tu dois interroger activemq en fonction d'un événement réseau, comme l'ouverture d'une connexion sur un port précis, tu peux utiliser la solution d'Amaury, à savoir un script démonisé par inetd/xinitd.
Mais je pense qu'il faut te demander l'intérêt de modifier ta solution, si elle est fonctionnelle et qu'il y a dans ta société les compétences et les connaissances nécessaire à sa maintenance.
28 De funkyproject - 10/05/2011, 07:40
@mageekguy: Il n'y a pas pour le moment pas d'intérêt à modifier la solution, mais je suis toujours à la recherche d'amélioration potentiel dans tout ce que je fais.
Remise en cause permanente, peut être une déformation d'agiliste
Merci de ta réponse en tout cas. Je me rend compte en écrivant que je cherche à pallier au multi thread. J'ai besoin que la tache soit exécutée quasiment en même temps que le chargement en queue, il s'agit juste pour moi de délivrer la page html plus rapidement.