Tuto - vérifier l'externalisation des backups et leur cohérence

Bonjour à tous,

Un nouveau petit outil pour vérifier si les backups de son Jeedom sont correctement externalisés et semblent cohérents.
En préambule, un constat : on ne vérifie pas suffisamment fréquemment si les backups sont OK et externalisés … Qui s’est fait avoir lors de la dernière MAJ de plugin-cloudsyncpro, en s’apercevant plusieurs jour plus tard qu’il n’avait plus de backup dans son drive
Qui vérifie régulièrement que la taille des backups Jeedom reste cohérent.

Ce petit scenario n’a pas vocation à verifier le contenu du backup. il ne verifiera pas si le backup se fait correctement.
PAR CONTRE, il alertera :

  • si la taille des backup est en dessous ou au dessus d’une certaine limite.
    Le fait d’avoir une taille trop petite ou trop grande peut signifier un pb dans le contenu du backup (ex: archives trop importantes - cf Tuto - analyser les archives pour détecter des pbs (lenteurs / espaces disques), ou sauvegarde de vidéos issues des cameras - sans intérêt avec de la place utilisée pour rien et un risque de corruption du backup
  • si il n’y a pas de backup transféré dans son stockage externalisé dans la journée en cours
    Le fait de ne pas avoir de backup transféré peut signifier que le backup n’a pas été généré ou que le transfert n’a pas réussi. Dans tous les cas, une analyse de la cause du pb est indispensable

IL UTILISE LE plugin-cloudsyncpro via la fonction liste et envoie les notifs, en fonction du paramétrage soit au centre de message, soit à des notifications via plugin-jeedomconnect (mais doit aussi fonctionner avec plugin-jeemate ou tout autre outil gérant les notifs)


Voilà le retour du scenario :

[2023-04-29 04:21:26][SCENARIO] ┌──────────── Logs bloc code - version du 23/04/2023 16:00
[2023-04-29 04:21:26][SCENARIO] | Fichier log : cloudsyncpro.#40354
[2023-04-29 04:21:26][SCENARIO] | Taille min  : 250Mo
[2023-04-29 04:21:26][SCENARIO] | Taille max  : 300Mo
[2023-04-29 04:21:26][SCENARIO] | Résumé : domo_stlattier (Version : 4.4.0)
[2023-04-29 04:21:26][SCENARIO] |     Nb backup presents   : 8
[2023-04-29 04:21:26][SCENARIO] |     1er backup dispo     : 21/04/2023
[2023-04-29 04:21:26][SCENARIO] |     dernier backup dispo : 28/04/2023
[2023-04-29 04:21:26][SCENARIO] |     Taille moyenne       : 216Mo
[2023-04-29 04:21:26][SCENARIO] | /!\ Pb de taille sur un backup - merci de vérifier (taille min : 215Mb, max :216Mb)
[2023-04-29 04:21:26][SCENARIO] | /!\ Pas de backup aujourd'hui
[2023-04-29 04:21:27][SCENARIO] | Résumé : domo_stetienne (Version : 4.4.0)
[2023-04-29 04:21:27][SCENARIO] |     Nb backup presents   : 8
[2023-04-29 04:21:27][SCENARIO] |     1er backup dispo     : 21/04/2023
[2023-04-29 04:21:27][SCENARIO] |     dernier backup dispo : 28/04/2023
[2023-04-29 04:21:27][SCENARIO] |     Taille moyenne       : 287Mo
[2023-04-29 04:21:27][SCENARIO] | /!\ Pas de backup aujourd'hui
[2023-04-29 04:21:27][SCENARIO] └───────────────────────────

Vous voyez qu’il gère plusieurs backups de plusieurs box Jeedom si vous êtes dans cette situation.

1 - création d’une commande listant le contenu du répertoire externalisé
Seule chose à faire à l’exterieure du scenario, dans son équipement du plugin plugin-cloudsyncpro, créer une commande de type liste et pointant vers son repertoire de destination des backup.

2 - mise en place du scenario de vérification
voilà le scenario à importer :
Backup_Check V2.json.txt (11,8 Ko)

V1 : version initiale
V2 : rajout de la taille du premier et du dernier backup

Modifier les quelques paramètres nécessaires :

  • La commande permettant de liste le rep de destination
  • les seuil haut et bas des tailles de backup
  • le type de notif souhaité et la commande de notification

Et voilà, reste plus qu’à lancer tout ca tous les jours et attendre les notifs en cas de pb … plus de raison de ne plus avoir de backups corrects

Remarque : il a été testé avec une externalisation GDrive. il peut y avoir quelques adapations à faire si les externalisations se font sur d’autres drives

Bonne implémentation
Norbert

8 « J'aime »

Bonjour
Est-ce que c’est possible de mettre en dessous de la taille moyenne la taille du dernier backup
Je ne sais pas écrire du code
Merci

Voilà …

[2023-05-03 19:40:27][SCENARIO] ┌──────────── Logs bloc code - version du 03/05/2023 19:00
[2023-05-03 19:40:27][SCENARIO] | Fichier log : /var/www/html/log/cloudsyncpro.#40354
[2023-05-03 19:40:27][SCENARIO] | Taille min  : 200Mo
[2023-05-03 19:40:27][SCENARIO] | Taille max  : 300Mo
[2023-05-03 19:40:47][SCENARIO] | Résumé : domo_stlattier (Version : 4.4.0)
[2023-05-03 19:40:47][SCENARIO] |     Nb backup presents   : 8
[2023-05-03 19:40:47][SCENARIO] |     1er backup dispo     : 26/04/2023 (215Mo)
[2023-05-03 19:40:47][SCENARIO] |     dernier backup dispo : 03/05/2023 (216Mo)
[2023-05-03 19:40:47][SCENARIO] |     Taille moyenne       : 216Mo
[2023-05-03 19:40:47][SCENARIO] | Résumé : domo_stetienne (Version : 4.4.0)
[2023-05-03 19:40:47][SCENARIO] |     Nb backup presents   : 8
[2023-05-03 19:40:47][SCENARIO] |     1er backup dispo     : 26/04/2023 (287Mo)
[2023-05-03 19:40:47][SCENARIO] |     dernier backup dispo : 03/05/2023 (287Mo)
[2023-05-03 19:40:47][SCENARIO] |     Taille moyenne       : 287Mo
[2023-05-03 19:40:47][SCENARIO] └───────────────────────────

et le bloc à remplacer (le template json initial a aussi été mis à jour)

// version bloc code
$version = '03/05/2023 19:00';
$scenario->setLog('┌──────────── Logs bloc code - version du ' . $version);

/**
* Class and Function List:
* Function list:
* - csv_to_array()
* Classes list:
*/

function csv_to_array($filename  = '', $delimiter = ',') {
    if (!file_exists($filename) || !is_readable($filename)) return false;

    $header    = array(
        'taille',
        'date',
        'heure',
        'file'
    );
    $data      = array();
    if (($handle    = fopen($filename, 'r')) !== false) {
        while (($row       = fgetcsv($handle, 1000, $delimiter)) !== false) {
            if (!$header) $header    = $row;
            else $data[]           = array_combine($header, $row);
        }
        fclose($handle);
    }
    return $data;
}

// parametres
$tags            = $scenario->getTags(); //récupère la liste des tags
$cmdIdListe      = str_replace('#', '', $tags['#cmdListe#']);
$seuilTailleMax  = $tags['#seuilTailleMax#'];
$seuilTailleMin  = $tags['#seuilTailleMin#'];
$AlerteCentreMsg = $tags['#AlerteCentreMsg#'];
$AlerteNotifJC   = $tags['#AlerteNotifJC#'];
$fichierListe    = '/var/www/html/log/cloudsyncpro.#' . $cmdIdListe;
if ($AlerteNotifJC) $cmdNotifJC      = cmd::byId(str_replace('#', '', $tags['#cmdNotifJC#']));

$scenario->setLog('| Fichier log : ' . $fichierListe);
$scenario->setLog('| Taille min  : ' . $seuilTailleMin . 'Mo');
$scenario->setLog('| Taille max  : ' . $seuilTailleMax . 'Mo');

// mise à jour de la liste
cmd::byId($cmdIdListe)->execCmd();

if (!file_exists($fichierListe) || !is_readable($fichierListe)) {
    $scenario->setLog('| /!\ le fichier ' . $fichierListe . ' n\'existe pas ou n\'est pas lisible');
    if ($AlerteCentreMsg) message::add('Backup', 'Vérification des backups, ERREUR : le fichier ' . $fichierListe . ' n\'existe pas ou n\'est pas lisible');
    if ($AlerteNotifJC) $cmdNotifJC->execCmd($options = array(
        'title'         => 'title=Defaut BACKUP ' . $site,
        'message'       => 'Vérification des backups, ERREUR : le fichier ' . $fichierListe . ' n\'existe pas ou n\'est pas lisible'
    ) , $cache   = 0);
}
else {
    // mise à jour de la liste
    cmd::byId($cmdIdListe)->execCmd();

    // Extraction des données du fichier dans un tableau
    $data = csv_to_array($fichierListe, ' ');

    // suppression des lignes vides
    for ($n    = 0;$n < count($data);$n++) {
        if (empty($data[$n][taille])) {
            array_splice($data, $n, 1);
        }
    }

    // recherche des sites de backup concernés
    for ($n = 0;$n < count($data);$n++) {
        $file                 = explode('-', $data[$n][file]);
        $sites[]                      = $file[1];
    }
    $sites                = array_unique($sites);

    foreach ($sites as $site) {
        $nbBackup             = 0;
        $tailleTotale         = 0;
        $tailleMax            = '';
        $tailleMin            = '';
        $backupToday          = 0;
        $tailleFirstBackup	  = 0;
        $tailleLastBackup	  = 0;
        $timestampFirstBackup = '';
        $timestampLastBackup  = '';

        for ($n                    = 0;$n < count($data);$n++) {
            $file    = explode('-', $data[$n][file]);
            if ($site == $file[1]) {
                // $scenario->setLog($site.'  -  '.$file[1]) ;
                $taille  = round($data[$n][taille] / 1024 / 1024);
                $file    = explode('-', $data[$n][file]);
                $jeedom  = $file[1];
                $version = $file[2];

                // $scenario->setLog($jeedom.' version '.$version.' taille '.$taille.'Mo '.date("d/m/y", $date));
                // nb de backup, taille totale et taille des backups
                $nbBackup++;
                $tailleTotale         = $tailleTotale + $taille;
                if ($taille > $tailleMax || empty($tailleMax)) $tailleMax            = $taille;
                if ($taille < $tailleMin || empty($tailleMin)) $tailleMin            = $taille;

                // date des backu^p
                $timestampBackup      = mktime(0, 0, 0, $file[4], $file[5], $file[3]); // timstamp du backup )à 0à:00
                $timestampNow         = mktime(0, 0, 0, date('m') , date('d') , date('Y'));
                if ($timestampBackup == $timestampNow) $backupToday          = 1;
                if ($timestampBackup <= $timestampFirstBackup || empty($timestampFirstBackup)) {
                  $timestampFirstBackup = $timestampBackup;
                  $tailleFirstBackup = $taille ;
                }
                if ($timestampBackup >= $timestampLastBackup || empty($timestampLastBackup)) {
                  $timestampLastBackup  = $timestampBackup;
                  $tailleLastBackup = $taille ;
                }
                  

            }
        }
        $scenario->setLog('| Résumé : ' . $site . ' (Version : ' . $version . ')');
        $scenario->setLog('|     Nb backup presents   : ' . $nbBackup);
        $scenario->setLog('|     1er backup dispo     : ' . date('d/m/Y', $timestampFirstBackup).' ('.$tailleFirstBackup.'Mo)');
        $scenario->setLog('|     dernier backup dispo : ' . date('d/m/Y', $timestampLastBackup).' ('.$tailleLastBackup.'Mo)');
        $scenario->setLog('|     Taille moyenne       : ' . round($tailleTotale / $nbBackup) . 'Mo');

        // gestion des erreurs
        if ($tailleMax >= $seuilTailleMax || $tailleMin <= $seuilTailleMin) {
            $scenario->setLog('| /!\ Pb de taille sur un backup - merci de verifier (taille min : ' . $tailleMin . 'Mb, max :' . $tailleMax . 'Mb)');
            if ($AlerteCentreMsg) message::add('Backup', $site . ' - Pb de taille sur une sauvegarde - merci de verifier (taille min : ' . $tailleMin . 'Mb, max :' . $tailleMax . 'Mb)');
            if ($AlerteNotifJC) $cmdNotifJC->execCmd($options = array(
                'title'         => 'title=Defaut BACKUP ' . $site,
                'message'       => 'Pb de taille sur un backup<br>Taille min : ' . $tailleMin . 'Mb<br>Taille max :' . $tailleMax . 'Mb'
            ) , $cache   = 0);
        }
        if ( !$backupToday) {
            $scenario->setLog('| /!\ Pas de backup aujourd\'hui');
            if ($AlerteCentreMsg) message::add('Backup', $site . ' - Pas de backup aujourd\'hui, dernier backup : ' . date('d/m/Y', $timestampLastBackup));
            if ($AlerteNotifJC) $cmdNotifJC->execCmd($options = array(
                'title'         => 'title=Defaut BACKUP ' . $site,
                'message'       => 'Pas de backup aujourd\'hui<br>Dernier backup : ' . date('d/m/Y', $timestampLastBackup)
            ) , $cache   = 0);
        }
    }
}

$scenario->setLog('└───────────────────────────');

Nikel le rajout de la taille du dernier backup
Est-ce que c’est possible d’envoyer la notification sur le télégramme ?

Je ne sais pas comment fonctionne une notif télégrame donc je ne saurais pas trop te dire.
As tu juste essayé de mettre ta commande de notif télégrame à la place de la notif jeedomconnect ?

Norbert

Salut,

Ce n’est pas aussi direct (mais c’est pas beaucoup de modif). J’ai bossé dessus tantôt.
Dès que je suis devant mon pc ce soir je propose une modif.

2 « J'aime »

J’ai essayé mais ça ne fonctionne pas
J’ai déjà vu une technique dans un code qui consiste a par exemple à mettre le texte qui est affiché dans le centre des messages dans une variable et après faire ajouter un bloc action pour l’envoyer sur telegram, par contre je ne sais pas créer la variable dans un bloc code

Salut,

Template :
Backup_Check_Telegram.json.txt (13,7 Ko)

Je n’ai pas vérifié de manière exhaustive, mais cela fonctionne au moins sur l’alerte de taille.

1 « J'aime »

Salut,

Je te propose pour simplifier de remplacer :

cmd::byId(str_replace('#', '', $tags['#cmdNotifJC#']));
cmd::byId(str_replace('#', '', $tags['#cmdNotifTelegram#']));

par :

cmd::byString($tags['#cmdNotifJC#']);
cmd::byString($tags['#cmdNotifTelegram#']);

Et ca marche chez toi ?
Chez moi, lorsque je mets une commande dans un tag avec les # (indispensable si on veut que la commande soit modifier dans le scenario en cas de changement du nom de la commande source), au niveau du bloc code, je me retrouve avec l’ID de la commande entouré de # … Du coup, necessité de supprimer les # (str_replace) et de fair eune recherche byId

Norbert

1 « J'aime »

Sans problème :

if ($AlerteNotifJC) $cmdNotifJC      = cmd::byString($tags['#cmdNotifJC#']);
if ($AlerteNotifTelegram) $cmdNotifTelegram      = cmd::byString($tags['#cmdNotifTelegram#']);
[2023-05-03 22:04:07][SCENARIO] -- Start : Scenario lance manuellement.
[2023-05-03 22:04:07][SCENARIO] - Exécution du sous-élément de type [action] : action
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #cmdListe# => #6189#
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #seuilTailleMin# => 20
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #seuilTailleMax# => 30
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #AlerteCentreMsg# => 0
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #AlerteNotifJC# => 0
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #AlerteNotifTelegram# => 1
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #cmdNotifJC# => #5593#
[2023-05-03 22:04:07][SCENARIO] Mise à jour du tag #cmdNotifTelegram# => #80#
[2023-05-03 22:04:07][SCENARIO] - Exécution du sous-élément de type [action] : code
[2023-05-03 22:04:07][SCENARIO] Exécution d'un bloc code 
[2023-05-03 22:04:07][SCENARIO] ┌──────────── Logs bloc code - version du 03/05/2023 21:00
[2023-05-03 22:04:07][SCENARIO] | Fichier log : /var/www/html/log/cloudsyncpro.#6189
[2023-05-03 22:04:07][SCENARIO] | Taille min  : 20Mo
[2023-05-03 22:04:07][SCENARIO] | Taille max  : 30Mo
[2023-05-03 22:04:27][SCENARIO] | Résumé : SARAH (Version : 4.3.17)
[2023-05-03 22:04:27][SCENARIO] |     Nb backup presents   : 14
[2023-05-03 22:04:27][SCENARIO] |     1er backup dispo     : 20/04/2023 (139Mo)
[2023-05-03 22:04:27][SCENARIO] |     dernier backup dispo : 03/05/2023 (139Mo)
[2023-05-03 22:04:27][SCENARIO] |     Taille moyenne       : 139Mo
[2023-05-03 22:04:27][SCENARIO] | /!\ Pb de taille sur un backup - merci de verifier (taille min : 139Mb, max :139Mb)
[2023-05-03 22:04:27][SCENARIO] └───────────────────────────
[2023-05-03 22:04:27][SCENARIO] Fin correcte du scénario

Et je recois bien la notif sur Telegram.

1 « J'aime »

De mémoire, le byString fonctionne avec l’id entouré de #.

1 « J'aime »

Sympa comme script. J’ai juste été obligé d’ajouter un champ au début dans le tableau $headers pour que ça fonctionne. En regardant le fichier log, je vois que les lignes commencent par un espace, je suppose que c’est la raison.

Et il y aussi la mise à jour de la liste qui est faite deux fois.

Je ne suis pas un expert PHP (et pas dev du tout :joy:), j’ai découvert sur le tas avec Jeedom ! Donc je ne m’offusquerai absolument pas de nouvelles versions du code optimisées et faites dans les règles de l’art … Au contraire, je prends toutes les bonne normes de développement :wink:

Norbert

1 « J'aime »

C’était bien l’idée, que ça puisse servir à quelqu’un. Moi aussi c’est plutôt de la bidouille en PHP.

Là je viens de mettre le script sur un autre Jeedom, et bien ça marche sans l’ajout du champ dans $headers. Mais les lignes du fichier log ne commencent pas par des espaces. Pourtant c’est la même version du plugin Cloud Sync Pro, va comprendre.

Génial ce script ! Ca va bien me servir. Merci à vous pour le partage et les contributions.

Personnellement j’ai remplacé les notif JeedomConnect par des notifs Jeemate et ca fonctionne sans problème :+1:

Je vais voir si je peux l’adapter à Dropbox :stuck_out_tongue:

2 « J'aime »

Bonjour,

En effet la mise à jour de la liste avant le if me semble inutile. Étant donné que tu la fait dans le bloc else.

Hello,

Merci @ngrataloup pour ce partage et ce script très pratique !

Pour info, de mon coté j’utilise cloudsyncpro vers un NAS en FTP et ça fonctionne correctement sans adaptation :slight_smile:

Bon ben en fait… Pas besoin de l’adapter pour Dropbox.
Il suffit de mettre directement la commande Liste en entrée du script, et ça marche niquel !

En fait, je pense que la fonction list utilisée par cloudsyncpro (rclone) renvoie le même format quelquesoit le protocole (gdrive, dropbox, ftp, …)
rclone lsl renvoie

$ rclone lsl swift:bucket
    60295 2016-06-25 18:55:41.062626927 bevajer5jef
    90613 2016-06-25 18:55:43.302607074 canole
    94467 2016-06-25 18:55:43.046609333 diwogej7
    37600 2016-06-25 18:55:40.814629136 fubuwic

Norbert