Deamon redémarre toutes les 5 minutes en mode automatique

Salut

Premier développement d’un plugin basé sur un daemon et je viens de voir qu’il redémarre toutes les 5mn uniquement quand il est en mode automatique.

Dans les logs j’ai le « signal 15 exiting », shutdown puis démarrage.

Je ne comprends pas la cause. De quoi ça peut venir puisque ça ne se produit pas quand il n’est pas en mode automatique ?

Salut,
Tu as configuré un heartbeat?
On peut voir la page de config et les logs? :wink:

Le démon est bien en statut OK pendant ces 5 min?
Tu as quoi dans ton daemon_info?

Salut,

Non pas de hearbeat de configuré.

Je viens de passer en automatique et démarré le demon (8:33:25).

Il a restart à 08:35:06

Les logs du demon :

[2023-08-05 08:33:26][INFO] : Start demond
[2023-08-05 08:33:26][INFO] : Log level : debug
[2023-08-05 08:33:26][INFO] : Socket port : 55009
[2023-08-05 08:33:26][INFO] : Socket host : localhost
[2023-08-05 08:33:26][INFO] : PID file : /tmp/jeedom/blitzortung/deamon.pid
[2023-08-05 08:33:26][INFO] : Apikey : ...
[2023-08-05 08:33:26][INFO] : Writing PID 1123188 to /tmp/jeedom/blitzortung/deamon.pid
[2023-08-05 08:33:26][INFO] : Init request module v2.25.1
[2023-08-05 08:33:26][DEBUG] : Starting new HTTP connection (1): 127.0.0.1:80
[2023-08-05 08:33:26][DEBUG] : http://127.0.0.1:80 "GET /plugins/blitzortung/core/php/jeeblitzortung.php?apikey=... HTTP/1.1" 200 0
[2023-08-05 08:33:26][INFO] : Socket interface started
[2023-08-05 08:33:26][INFO] : LoopNetServer Thread started
[2023-08-05 08:33:26][INFO] : Listening on: [localhost:55009]

.....

[2023-08-05 08:35:05][DEBUG] : Signal 15 caught, exiting...
[2023-08-05 08:35:05][DEBUG] : Shutdown
[2023-08-05 08:35:05][DEBUG] : Removing PID file /tmp/jeedom/blitzortung/deamon.pid
[2023-08-05 08:35:07][INFO] : Start demond
[2023-08-05 08:35:07][INFO] : Log level : debug
[2023-08-05 08:35:07][INFO] : Socket port : 55009
[2023-08-05 08:35:07][INFO] : Socket host : localhost
[2023-08-05 08:35:07][INFO] : PID file : /tmp/jeedom/blitzortung/deamon.pid
[2023-08-05 08:35:07][INFO] : Apikey : ...
[2023-08-05 08:35:07][INFO] : Writing PID 1126188 to /tmp/jeedom/blitzortung/deamon.pid
[2023-08-05 08:35:07][INFO] : Init request module v2.25.1
[2023-08-05 08:35:07][DEBUG] : Starting new HTTP connection (1): 127.0.0.1:80
[2023-08-05 08:35:07][DEBUG] : http://127.0.0.1:80 "GET /plugins/blitzortung/core/php/jeeblitzortung.php?apikey=... HTTP/1.1" 200 0
[2023-08-05 08:35:07][INFO] : Socket interface started
[2023-08-05 08:35:07][INFO] : LoopNetServer Thread started
[2023-08-05 08:35:07][INFO] : Listening on: [localhost:55009]

Si je laisse tourner comme ça, il est bien OK pendant les 5mn à chaque fois puis je fini par avoir le message indiquant que le demon a été restart 3 fois.

J’ai désactivé l’automatique à 08:36 environ, il est 08h41 et le dernier restart est toujours à 08:35:06
Pas de message dans les logs donc il tient.

Dans le code j’ai un cron Jeedom qui tourne toutes les 5mn, je pensais que quelque chose dans le code posait problème mais je l’ai retiré et c’est toujours pareil. Et puis comme le demon tient an mode normal ça n’avait pas de sens que ce soit lié au cron 5mn.

Je n’ai pas ce fichier. Il n’est pas dans le template, il le faut ?

EDIT : Ah pardon tu parles de la fonction :

  public static function deamon_info() {
    $return = array();
    $return['log'] = __CLASS__;
    $return['state'] = 'nok';
    $pid_file = jeedom::getTmpFolder(__CLASS__) . '/deamon.pid';
    if (file_exists($pid_file)) {
      if (@posix_getsid(trim(file_get_contents($pid_file)))) {
        $return['state'] = 'ok';
      } else {
        shell_exec(system::getCmdSudo() . 'rm -rf ' . $pid_file . ' 2>&1 > /dev/null');
      }
    }
    $return['launchable'] = 'ok';

    return $return;
  }

En mode auto, le core vérifie toutes les 5min si le démon tourne et le relance si besoin

Ma main au feu que c’est ce process qui relance ton démon

Par contre la via téléphone je vois pas et comme on vient d’arriver à notre prochain hôtel je vais faire un tour à la piscine :sunglasses:

Hello,

Etonnant car il me semble que si pas de heartbeat::delay le core ne relance pas le démon, et de plus la case Redémarrer démon n’est pas activé non plus :thinking:

Edit : ah non je m’embrouille, J’ai encore l’esprit en vacance :rofl: pour le heartbeat c’est un autre cron, toi c’est le checkDeamon

1 « J'aime »

Pas d’idée de ce que je peux tenter de modifier pour voir ce qu’il se passe lors de cette étape ?

Basiquement je comprends pourquoi il décide de le relancer :upside_down_face:

Tu as quoi dans ton deamon_start ?

 public static function deamon_start() {
    self::deamon_stop();
    self::getFreePort();
    $deamon_info = self::deamon_info();
    if ($deamon_info['launchable'] != 'ok') {
      throw new Exception(__('Veuillez vérifier la configuration', __FILE__));
    }

      $path = realpath(dirname(__FILE__) . '/../../resources/blitzortungd'); // répertoire du démon
    $cmd = 'python3 ' . $path . '/blitzortungd.py'; // nom du démon
    $cmd .= ' --loglevel ' . log::convertLogLevel(log::getLogLevel(__CLASS__));
    $cmd .= ' --socketport ' . config::byKey('socketport', __CLASS__); // port par défaut défini via la fonction getFreePort()
    $cmd .= ' --callback ' . network::getNetworkAccess('internal', 'proto:127.0.0.1:port:comp') . '/plugins/blitzortung/core/php/jeeblitzortung.php'; // chemin de la callback url à modifier (voir ci-dessous)
    $cmd .= ' --apikey ' . jeedom::getApiKey(__CLASS__); // l'apikey pour authentifier les échanges suivants
    $cmd .= ' --pid ' . jeedom::getTmpFolder(__CLASS__) . '/deamon.pid'; // chemin vers le pid file
    log::add(__CLASS__, 'info', 'Lancement démon');
    $result = exec($cmd . ' >> ' . log::getPathToLog('blitzortungd') . ' 2>&1 &'); // nom du log pour le démon
    $i = 0;
    while ($i < 20) {
      $deamon_info = self::deamon_info();
      if ($deamon_info['state'] == 'ok') {
        break;
      }
      sleep(1);
      $i++;
    }
    if ($i >= 30) {
      log::add(__CLASS__, 'error', __('Impossible de lancer le démon, vérifiez le log', __FILE__), 'unableStartDeamon');
      return false;
    }
    message::removeAll(__CLASS__, 'unableStartDeamon');
    return true;
  }

et le getFreePort() mais qui ne fait rien du tout cas je n’ai pas compris encore comment faire passer ça coté python et le port est toujours en dur dans cette partie .py

  public static function getFreePort() {
    $freePortFound = false;
    while (!$freePortFound) {
      $port = mt_rand(50000, 65000);
      exec('sudo fuser ' . $port . '/tcp', $out, $return);
      if ($return == 1) {
        $freePortFound = true;
      }
    }
    config::save('socketport', $port, 'blitzortung');
    return $port;
  }

Ça va poser problème le getfreeport => il choisi et sauve un port rando mais ensuite le config:bykey va prendre la valeur dans le cache si elle existe donc déjà ça sera quasi jamais celle sauvée en db
D’autres part, si ça prend un port d’un autre plugin ça va planter l’autre démon ou le tiens à un moment

Je vois bien l’idée, elle n’est pas neuve, mais selon moi soit c’est le core qui gère une table et qui distribue les ports aux plugins (comme un dhcp) soit ça doit être fixé une fois pour toute dans la config avec une proposition par défaut.

Debug un truc qui change en random c’est foireux

Du coup ton port en dur dans ton code python, t’as pas un conflit?

image
Tu ne pourra jamais être dans ta 2eme condition car ta boucle s’arrêtera forcement a 20

Non ce port n’est pas utilisé chez moi. J’ai bien pensé aussi à ça mais j’aurais un autre plugin en vrac et surtout en manuel ça marcherait pas non plus.

Je vais repartir depuis daemon_start sur un port au pif et l’ajouter dans la configuration pour possibilité de le changer.

C’est dommage de pas avoir une base de l’ensemble des ports des plugins tout de même, ça serait plus simple de piocher dans ce qui n’existe pas encore.

En effet je n’avais pas vu ça, j’ai repris ce qui était dans le template. Mais je vois toujours pas pourquoi ça bloque pas au démarrage dès l’exécution du démon.

Faudrait mettre 30 aussi dans le 1er d’après toi ?

Met la même valeur 20 ou 30

effectivement il y a une erreur dans le template.

C’est pas la seule :wink:.

Il y a un truc je sais plus où sur exception, et faut as.
Et apparemment autre chose qui manque et que j’ai vu dans la doc que Mips avait du faire si je ne m’abuse.

Je voulais ouvrir un post là dessus pour vous demander confirmation aussi et rectifier le plugin template.

Bon j’essaie de mettre 20 de partout et refixer le port dans le .PHP du répertoire core dès que j’arrête de charrier du sable chez moi.

J’utilise ça dans mes plugins sans que ça pose de soucis


Fonction pour trouver un port free
	public static function getFreePort() {
		$freePortFound = false;
		while (!$freePortFound) {
			$port = mt_rand(1024, 65535);
			exec('sudo fuser '.$port.'/tcp',$out,$return);
			if ($return==1) {
				$freePortFound = true;
			}
		}
		config::save('socketport',$port,'enphasesecur');
		return $port;
	}

Et ça pour la partie start


	$i = 0;
        while ($i < 20) {
            $deamon_info = self::deamon_info();
            if ($deamon_info['state'] == 'ok') {
                break;
            }
            sleep(1);
            $i++;
        }
        if ($i >= 30) {
            log::add(__CLASS__, 'error', __('Impossible de lancer le démon, vérifiez le log', __FILE__), 'unableStartDeamon');
            return false;
        }
        message::removeAll(__CLASS__, 'unableStartDeamon');
        return true;


Et la fonction de contrôle


public static function deamon_info() {
        $return = array();
        $return['log'] = __CLASS__;
        $return['state'] = 'nok';
        $pid_file = jeedom::getTmpFolder(__CLASS__) . '/deamon.pid';
        if (file_exists($pid_file)) {
            if (@posix_getsid(trim(file_get_contents($pid_file)))) {
                $return['state'] = 'ok';
            } else {
                shell_exec(system::getCmdSudo() . 'rm -rf ' . $pid_file . ' 2>&1 > /dev/null');
            }
        }
        $return['launchable'] = 'ok';

		if (config::byKey('ctoken', __CLASS__) == 'auto'){
        	//if ((config::byKey('user', __CLASS__) == '') || (config::byKey('password', __CLASS__) == '') || (config::byKey('site', __CLASS__) == '') || (config::byKey('ip', __CLASS__) == '') || (config::byKey('serie', __CLASS__) == '')) {
			if ((config::byKey('user', __CLASS__) == '') || (config::byKey('password', __CLASS__) == '') || (config::byKey('ip', __CLASS__) == '') || (config::byKey('serie', __CLASS__) == '')) {
	
				$return['launchable'] = 'nok';
            	$return['launchable_message'] = __('Toutes les informations obligatoires ne sont pas remplies', __FILE__);
			}
		}
		else {
			if ((config::byKey('token', __CLASS__) == '') || (config::byKey('ip', __CLASS__) == '')) {
            	$return['launchable'] = 'nok';
            	$return['launchable_message'] = __('Toutes les informations obligatoires ne sont pas remplies', __FILE__);
			}
		}
        return $return;
    }


J’avais vu, c’est sur ton plugin que j’ai été repiquer la fonction mais apparemment :

  • ça ne fait rien d’après ce que je constate
  • Mips dit qu’il va chercher la valeur dans le cache et donc ne reprend pas un nouveau port si besoin

De ce que j’ai vu le « problème » c’est que finalement, le port qui est utilisé est défini dans le fichier python

Je viens de modifier le port en 55017 dans cette partie :

_log_level = "error"
_socket_port = 55017
_socket_host = 'localhost'
_pidfile = '/tmp/demond.pid'
_apikey = ''
_callback = ''
_cycle = 0.3

Et le démon démarre sur 55017 … il se fou totalement de ce qu’il y a dans le code php (dans deamon_start() d’après ce que je constate.

188291|[2023-08-05 17:40:58]INFO : Start demond
188292|[2023-08-05 17:40:58]INFO : Log level : info
188293|[2023-08-05 17:40:58]INFO : Socket port : 55017
188294|[2023-08-05 17:40:58]INFO : Socket host : localhost
188295|[2023-08-05 17:40:58]INFO : PID file : /tmp/jeedom/blitzortung/deamon.pid

idem tu as recopié la même coquille,
while ($i < 20) et ensuite condition if ($i >= 30), tu ne sera donc jamais dans cette condition et donc la fonction renvera toujours true.

Bon, alors le mystère épaissie car en fait, sur mon environnement de dev, le daemon tient bon en automatique. Jusque là j’avais laissé en manuel pour développer et c’est en passant sur ma prod pour valider le fonctionnement que j’ai remarqué le problème.

Du coup je présume qu’il y a un rapport avec la version du core ?

Dev : Jeedom beta 4.4 mis à jour hier
Prod : Jeedom stable 4.3.17

Est-ce qu’il y aurait quelque chose qui peut expliquer ça ?

Pas faux mais de toute façon je kill le d’admin en python si erreur donc j’ai jamais remarqué la coquille

Pour l’histoire des ports libre, j’avais fait des tests et ça fonctionnait pas mal. Mieux que d’imposer un port et je n’ai jamais eu d’utilisateur avec un soucis de port