Créer un démon en php

Salut à tous !

Je travaille actuellement sur un projet de metrologie de réseau, et j’ai besoin de lancer régulièrement des fonctions php qui me calculent des statistiques à partir d’une base de données postgreSQL.
Pour l’instant j’utilise crontab, mais je voudrais remplacer ça par un démon qui me lancerai mes fonctions à intervalle régulier, en s’assurant ke la précédente s’est bien terminée, et en stockant des logs dans ma bdd.

Est ce que quelqu’un pourrai me dire s’il existe un moyen de créer un démon en php ??
Si oui, comment?
Si vous avez de la doc, je suis prenneur…

Merci de votre collaboration

Alors je ne sais pas si un “démon” est faisable, cependant j’ai une idée toute bête qui pourrait marcher: tu fais un script php qui fonctionne comme le démon, et tu mets une balise meta qui s’actualise toute les x secondes. Ainsi l’opération sera relancée toutes les x secondes, libre à toi ensuite de faire les vérifications et sauvegardes de logs après une actualisation.


#!/usr/bin/php
<?php

//Fonction pour l'écriture des logs
function writetolog($text)
{
   $datenow = date("d/m/Y H:i:s");
   print "[$datenow] addzapuserd: $text\n";
}


while (1==1) //Boucle principale d'où le script-daemon ne sort jamais
{

// Ton code ici

sleep(60); //Le script-daemon "dort" pendant 60 secondes avant de recommencer sa tache ingrate :)

}

?>

Voila :wink:
Il faut quand même le lancer au démarrage (ou manuellement) :smiley:

je trouve ça H O R R I B L E :vomi:

le cron c’est vraiment mieux.
et pour savoir si le script c’est bien terminé, crée un fichier temporaire au lancement et supprime le avant de le fermer. si le fichier est encore la au prochain lancement, alors ça c’est mal arrêté :jap:

Sinon while (1==1) == while (true) == for (;:wink:

(vive le for, pas besoin d’évaluer quoi que ce soit = un peu plus rapide)

C’est bon, j’ai trouvé comment faire,
Je fait un fork(), puis un seteuid(0) et setsid() comme ça je me détache du processus parent…
Ensuite j’ai ma boucle while($ok === true)
J’écoute sur ma socket, si message -> répond ou quitte, sinon, je passe à autre chose…

function start(){
$pid = pcntl_fork();
if ($pid == -1) {
die(‘dupplication impossible’);
}
elseif ($pid) {
// le père
//pcntl_wait($status); //Protège encore des enfants zombies
exit(0);
}
else {
// le fils
/* On se detache du papa*/
if(!posix_seteuid(0)){
echo “Error Changing effective uid.\n”;
exit(-1);
}
if(!posix_setsid()){
echo “Erreur detachement processus.\n”;
exit(-1);
}
/On créé un fichier dans lequel on stocke le pid/
/* On ouvre le fichier*/
if(!$handle = fopen($this->filename, ‘w+’)){
echo “Impossible d’écrire dans le fichier “.$this->filename.”. Etes vous root?\n”;
exit(-1);
}
/* On recupere le pid du processus fils*/
if(!$pid = getmypid()){
echo “Impossible de récupérer le pid.\n”;
exit(-1);
}
//echo “Pid du processus :”.$pid."\n";
/On ecrit le pid dans le fichier /
if (fwrite($handle, $pid) === FALSE) {
echo “Impossible d’écrire dans le fichier ($this->filename)”;
exit(-1);
}
fclose($handle);
/On créé la socket/
$this->socket = socket_create(AF_UNIX,SOCK_STREAM, 0);
if ($this->socket === false) {
//echo “$errstr ($errno)<br />\n”;
echo “Impossible de créer une socket: “.socket_strerror(socket_last_error($this->socket)).”\n”;
exit(-1);
}
/On lie la socket/
if(socket_bind($this->socket, ‘/var/run/metro.socket’) === false){
echo “Impossible de lier la socket :”.socket_strerror(socket_last_error($this->socket))." \n";
exit(-1);
}
/Creation de la file d’attente/
if(socket_listen($this->socket, 10) === false){
echo “Erreur lors de la creation de la file d’attente de la socket\n”;
exit(-1);
}
$read = array($this->socket);
$ok = true;
while ($ok == true){
if( ($changed_socket = socket_select($read,$write = NULL, $except = NULL, 5)) === false){
echo “Erreur socket_select \n”;
}
elseif($changed_socket > 0){
/
La socket a été modifiée on l’accepte
/
if(($conn = socket_accept($this->socket)) === NULL){
echo “Erreur socket_accept :”.socket_strerror(socket_last_strerror($this->socket))."\n";
}
elseif(($buf = socket_read($conn, 2048)) === NULL){
echo “Erreur de lecture sur la socket :”.socket_strerror(socket_last_strerror($this->socket))."\n";
}
else{
switch ($buf){
case ‘status’:
$text ="\nLe Démon tourne !!\n".
“L\'heure locale est “.date(‘j-n-Y g:i a’).”\n”;
socket_write($conn, $text);
break;
case ‘stop’:
$text = “\nFermeture du démon…”;
socket_close($this->socket);
$text .= “ok!\n”;
$ok = false;
socket_write($conn, $text);
//exit(0);
break;
default :
$text = “yabadabadoooo\n”;
socket_write($conn, $text);
break;
}
}
socket_close($conn);
}
else{
/La socket n’est pas modifiée, on continue/
echo “Hello world!\n”;
}
}
}
}

Voila, ça marche preske, le socket_select me retourne toujours une valeur négative, et donc je pert la communication avec mon processus.
Faudrai trouver un moyen de simuler des threads en php, ce ki n’existe pas je crois…

pour benj :
C vrai que la solution du cron est pratique, mais comme ma base de données est assez balèse et que mes requetes peuvent durer super longtemps, je suis obligé d’attendre ke l’instance de calcul précédente soit terminée.
(durée fonction = 4 à 6 min) a executer toutes les 5 mins… lol
PS : Ce démon n’est pas fait pour tourner dans un navigateur…

Et qu’est-ce qui se passe si on accède à tes données pendant qu’elles sont en train d’être mises à jour ? T’utilises une transaction de 5 minutes ? O_o

Les threads en php, ça n’existe pas, non. Mais deux questions :

  • pourquoi un socket_select pour gérer un seul socket ? Moi j’aurais mis le socket_accept direct.
  • pourquoi un timeout de 5 secondes dans ton socket_select ?

Y a un bon exemple ici : http://fr3.php.net/manual/en/ref.sockets.php.

Le timeout de 5 sec, c’est pour les tests…
Je fait un select sur ma socket pour pouvoir justement effectuer une autre tache que répondre kan persone me parle…

Si on me demande un truc alors je répond
sinon je continue a bosser…

En gros c ça l’algo ke je souhaiterai metre ne place…

J’ai modifié les parametres de select_socket :
$write = $read = array($socket);
et là mon select me retourne 1 meme lorsue k’il n’y a aucun message sur la file d’attente…

OK.
L’intérêt du write, je le vois pas trop dans ton cas mais bon… je regarderai ça ce soir si j’ai le temps, là je suis au boulot…

Le write tu peu oublier, c’était un test d’avant, justement pour tester si mon demon est bien lancé, je regardais si le fichier existe.
et pour le fermer je killais le pid inscrit ds le fichier…
c pas tres propre mais ça marche…

Finalement, j’ai réussi !!!
au lieu d’initialiser ma variable $read = array($this->socket) avant le while, le l’ai mid directement dans le socket_select($read = array($this->socket), $write= null, $except = null, 5)
Et ça marche !!

Du coup j’ai un truc qui marche preske comme un thread et toutes les 5 secondes je peu effectuer un nouveau traitement …