Jeedom 4.5 - un manque de logs après le passage du crondaily

Bonjour,

Pas de souci de log ce matin.

  • Les logs de taille 0 reste à 0. Avec echo, il y a un caractère \0 qui s’ajoutait dans ces fichiers.
  • Les logs sont bien tronqués à 5000 lignes.

Ca pourrait encore être plus optimisé en combinant les options -n 5000 et -c10M de la commande tail. Ne fonctionne pas les options n et c sont exclusives.
Le tronquage n’est de toute façon pas toujours propre à cause des daemons qui tournent pendant que les fichiers de log sont tronqués.

Hello,

Je vais essayer ça aussi et je pense que l’on pourra proposer une PR ensuite

Hello @jpty,

C’est bon aussi chez moi avec ton code :+1:

L’équipe Jeedom on fait quoi du coup avec ce constat ? @Loic ? @Aurelien ?

1 « J'aime »

Bonjour,
Comme toujours nous avons bien pris le point et nous allons voir pour améliorer ce systeme mais vu qu’il est en place depuis plusieurs mois ce n’est pour le moment pas une urgence (le soucis arrivant chez très peu d’utilisateur).

Edit : ne pas oublier que vous pouvez proposer des PR pour accelerer les choses.

1 « J'aime »

Bonjour Loic,

OK merci de l’avoir indiqué, je n’avais pas vu de réaction de l’équipe donc je ne pouvais pas savoir que vous aviez pris le point :slight_smile:

Oui je sais que l’on peut faire une PR et c’était bien l’idée de ma sollicitation et de savoir ce que vous pensiez du code proposé par @jpty histoire d’avoir déjà une validation rapide et que l’on ne fasse pas de PR pour rien et encore moins si le point est déjà pris

Son code marche mais il va générer pas mal d’écriture disque (a l’inverse du traitement en mémoire) et donc réduira la durée de vie sur les systeme type rpi (sur carte SD) c’est pour ca qu’on avait choisi de pas faire cette méthode.

On va donc y réfléchir et voir ce qui est le mieux.

2 « J'aime »

Bonjour,

Dans tous les cas, il faut au moins supprimer le sudo (comme en 4.4) qui pose des pbs avec la taille de la ligne de commande.
La solution serait peut-être de créer le fichier intermédiaire en RAM dans un tmpfs comme /tmp/jeedom

Hello,

J’ai continué à réfléchir au sujet en partant de la proposition de jpty et de la contrainte des écritures sur les cartes SD.

Moi j’en suis là pour le moment :

        $sudo = system::getCmdSudo();
    	$uid = system::get('www-uid');
    	$gid = system::get('www-gid');
		try {
          	com_shell::execute("$sudo sh -c 'tail -n $maxLineLog $_path > $_path.tmp && mv $_path.tmp $_path && chown $uid:$gid $_path && chmod 664 $_path'");
		} catch (\Exception $e) {
		}

sh -c execute dans un shell root
tail lit le fichier et l’écrit dans un fichier temporaire sans charger quoi que ce soit en mémoire
mv remplace l’ancien fichier par le nouveau en modifiant le pointeur dans le système de fichiers ce qui sollicite vraiment très peu le disque

Du coup je pense que l’on ne sollicite pas plus le disque (ou la carte SD) qu’avec echo qui va charger en mémoire puis écrire d’un coup le résultat dans le fichier

L’avantage c’est que si la commande tail échoue pour une raison ou une autre, le fichier source ne sera pas écrasé

J’ai mis les chmod et chown à la fin parce que je ne comprends pas vraiment ce qu’il font en début de commandes. Vu que l’on exécute en root, il ne doit pas y avoir de problème de permission et ici owner/group sera cassés

Maintenant concrètement le chown ne devrait pas servir vu les 2 commandes après le try/catch

Je regarde encore demain matin ce que ça donne et je proposerais une PR sur la branche alpha

Avec mv, les daemons qui écrivait dans le fichier $_path à l’inode XXXX n’écriront jamais dans l’inode YYYY du nouveau fichier $_path créé par mv. Il faudrait relancer les daemons pour que le changement d’inode soit pris en compte.
Il faut faire cat $_path.tmp > $_path && rm $_path.tmp
En marche normale, les chown et chmod ne servent à rien. Il y a d’autres taches cron qui le font.

La fonction chunkLog avec :

  • le fichier intermédiaire dans le tmpfs de jeedom avec un nom fixe
  • le tronquage des fichiers à 10M puis à $maxLineLog lignes
  • la préservation de l’inode du fichier $_path pour les daemons
  • le tail étant exécuté en root, les chmod et chown ne sont pas utiles

Voir une version corrigée plus loin dans ce fil.

Le but était de prendre en compte la remarque de Loïc concernant les cartes SD.

Concernant ta remarque, concrètement, si un plugin a un démon, suite au mv il n’y aurait plus de nouvelles lignes de logs dans le fichier de log du démon ?

Oui exactement. mv crée un fichier avec un inode différent inconnu du daemon existant.
J’ai ajouté du code dans mon dernier post.
Le fichier intermédiaire est créé dans un tmpfs en RAM sans écriture sur la carte SD.
Il n’y a pas plus d’écriture sur la SD qu’avant

1 « J'aime »

Salut,

Bon j’essaie de remonter à nouveau le problème et je vais changer ajouter le tag en bug parce que j’ai migré le Jeedom de mes parents hier en 4.5.2 et je constate exactement la même chose que chez moi.

Exemple d’un scénario qui s’est lancé à 21:00 et qui n’a aucun log ce matin. Il y en a plein d’autres.

Dans le moteur le crondaily est à 2h43

Et une bonne partie des logs non alimentés depuis cette heure est à 0 (dont le 63 qui correspond à la capture que j’ai mis)

:grey_question: Ce serait possible de fixer ça please ?

1 « J'aime »

je propose ceci pour pas laisser des fichiers inutiles en cas d’erreur :

try {
    com_shell::execute("$sudo tail -c 10M $_path | tail -n $maxLineLog > $ftmp && cat $ftmp > $_path");
} catch (\Exception $e) {
} finally {
    com_shell::execute("rm -f $ftmp");
}
1 « J'aime »

Bonjour,

J’ai ajouté un sudo avant le cat et un avant ton rm au cas où. J’avais un log qui résistait:

Caught exception in chunkLog(): Erreur sur sudo tail -c 10M /var/www/html/core/class/../../log/homeconnect | tail -n 5000 > /tmp/jeedom/log.tmp && cat /tmp/jeedom/log.tmp > /var/www/html/core/class/../../log/homeconnect 2>&1 valeur retournée : 2. Détails : 

Ma dernière version de chunkLog() :
Supprimé.
Voir la version plus loin qui prend en compte le paramètre maxSizeLog de la 4.5.3

La fonction originale est dans le fichier core/class/log.class.php

3 « J'aime »

plus que @Bison à tester la nouvelle fonction, et après un petit PR qui va bien :slight_smile:

Hello nebz,

J’ai mis à jour avec cette version chez moi, je vérifie demain matin.

3 « J'aime »

Idem ! Fonction mise à jour ce matin ! Je vous redis si OK dans les 48h !
Merci @jpty pour le debug :wink:

Hello,

@jpty, @nebz, toujours pas de problème identifié chez moi avec ce nouveau code que ce soit au niveau des scénarios ou des logs avec des plugins qui ont des démons

1 « J'aime »

Bonjour

Ok chez moi également depuis 2 jours

Merci :slight_smile:

1 « J'aime »

Bonjour,

J’ai complété le souci avec un scénario qui vérifie si le tronquage a été correctement effectué.
Je le lance quelques minutes après l’exécution de jeedom::CronDaily
Il récupère le nombre de lignes maxi dans un log (maxLineLog), l’heure d’exec de jeedom::CronDaily (cronTime → cronTS ) et vérifie que l’heure sur la ligne maxLineLog-1 du log est inférieure à cronTS. Si la ligne maxLineLog ne contient pas d’heure, la ligne précédente est utilisée.

Le bloc code:
$dir = '/var/www/html/log';
$maxLineLog = config::byKey('maxLineLog', 'core', 200);
$cronTime = "today 01:01:00";
$cron = cron::byClassAndFunction('jeedom', 'cronDaily');
if(is_object($cron)) {
  $cronTime = $cron->getLastRun();
  $scenario->setLog("Jeedom cronDaily LastRun: $cronTime");
}
else $scenario->setLog("Jeedom cronDaily not found. Using " .date('Y-m-d H:i:s', strtotime($cronTime)));
$cronTS = strtotime($cronTime);

function listLog($dir, $sc, $maxLineLog, $cronTS, &$files) {
// $scenario->setLog("nLine: $maxLineLog");
  if ($handle = opendir($dir)) {
    while (false !== ($entry = readdir($handle))) {
        if ($entry === '.' || $entry === '..') {
            continue;
        }
    $file = "$dir/$entry";
    if (is_dir($file)) {
      listLog($file, $sc, $maxLineLog, $cronTS, $files);
        // $sc->setLog("Répertoire: " .$file);
      continue;
    }
    $nlig = intval(shell_exec("wc -l $file"));
    if($nlig < $maxLineLog +1) continue;
    $fc = file($file);
    $line = $fc[$maxLineLog-1]; // Cette ligne doit etre apres l'heure de tronquage
    $date = substr($line, 1, 19);
    $tsDate = strtotime($date);
    if($tsDate !== false) {
      if($tsDate > $cronTS) {
        $files[] = [ "name" => $entry, "size" => filesize($file), "#line" => $nlig, "entry" => "L{$maxLineLog}: $line"];
        // $sc->setLog("1KO: $entry $maxLineLog|$line");
      }
    }
    else { // Pas de date dans la ligne $maxLineLog-1. Verif dans la ligne précédente
      // $sc->setLog("Ligne sans heure: $entry $line");
      $line = $fc[$maxLineLog -2]; // ligne avant l'heure de tronquage
      // $sc->setLog("Verif ligne précédente: $entry $line");
      $date = substr($line, 1, 19);
      $tsDate = strtotime($date);
      if($tsDate !== false) {
        if($tsDate > $cronTS) {
          $files[] = [ "name" => $entry, "size" => filesize($file), "#line" => $nlig, "entry" => "L" .$maxLineLog-1 .": $line"];
          // $sc->setLog("2KO: $entry $maxLineLog-1|$line");
        }
      }
      else $sc->setLog("{$entry} Pas de date trouvée dans la ligne $maxLineLog.");
    }  // $scenario->setLog($entry);
  }
  closedir($handle);
}
}

$files = array();
listLog($dir, $scenario, $maxLineLog, $cronTS, $files);
if(count($files)) {
  uasort($files,function($a,$b) { return $b['#line'] - $a['#line']; }); // tri par nombre de lignes décroissant
  $txt = "\nLigne\tTaille\tNom\tContenu\n";
  foreach($files as $file) {
    $txt .= "{$file['#line']}\t{$file['size']}\t{$file['name']}\t{$file['entry']}\n";
  }
  $scenario->setLog($txt);
}
else $scenario->setLog("-- Logs correctement purgés --");

Pour le moment pas de logfile récalcitrant ( quand le log est correctement formaté ).

[2026-02-19 01:03:02][SCENARIO] -- Début : . Tags : {"#trigger#":"schedule","#trigger_name#":"","#trigger_id#":"","#trigger_message#":"Scénario exécuté automatiquement sur programmation","#trigger_value#":null}
[2026-02-19 01:03:02][SCENARIO] - Exécution du sous-élément de type [action] : code
[2026-02-19 01:03:02][SCENARIO] Exécution d'un bloc code
[2026-02-19 01:03:02][SCENARIO] Jeedom cronDaily LastRun: 2026-02-19 01:01:02
[2026-02-19 01:03:02][SCENARIO] -- Logs correctement purgés --
[2026-02-19 01:03:02][SCENARIO] Fin correcte du scénario
1 « J'aime »