Forum Programmation.shell Surveillance de la latence d'une liste d'hôte

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
1
3
sept.
2021

Bonjour à tous,

J'ai une liste d'IP dans un fichier (une ligne = une adresse IP). Le but est de surveiller la latence pour chacun d'entre eux toutes les secondes. Pour le moment j'en suis loin.. Je viens chercher un peu d'aide.. j'ai un peu de mal à écrire mon script :(

for i in `cat list_address`
do
ping $i > $i_$(date +%d%m%Y) | while read pong; do echo "$(date): $pong"; done
done

Pour la conservation des données. J'aimerais conserver les résultats comme ci-dessous :
Un répertoire par jour, avec chaque fichier de logs pour chaque adresses à l'intérieur.

Jour1/ |
--------- IP1
--------- IP2
Jour2/ |
--------- IP1
--------- IP2

  • # Toutes les secondes ?

    Posté par  (site Web personnel) . Évalué à 4.

    Mesurer la latence toutes les secondes, n'est-ce pas un peu excessif ? Ca va te faire 86400 mesures par jour et par IP ! Une mesure toutes les 30 secondes ne suffit pas ? En fait c'est quoi le but du jeu ?

    Vu que la mesure peut prendre du temps, si la latence est supérieure à 1 seconde, tu prévois quel comportement ? Il y a au choix :
    - faire le bourrin et lancer une mesure toutes les secondes, même si l'IP est aux fraises et met trois plombes à répondre, quitte à aggraver sa triste situation par tes mesures.
    - ne pas lancer d'autres mesures tant que la précédente n'a pas aboutie, ce qui donnera des trous dans les mesures, mais alors tu as aussi deux choix :
    -- lancer une mesure dès que celle qui a mis plus d'une seconde est terminée, donc on n'est plus calé sur des secondes pile-poil.
    -- attendre la prochaine seconde pile-poil pour lancer la mesure suivante pour être calé avec les mesures précédentes.

    Faut déjà que tu décides quel comportement adopter, cela en fonction de ton besoin. Ensuite faire le script ne sera pas difficile : un script principal qui lance autant de daemons que d'IP dans le fichier, chaque daemon fait la mesure (en fonction du comportement que tu as choisi) et stocke la valeur dans un fichier ou BDD.

    • [^] # Re: Toutes les secondes ?

      Posté par  . Évalué à 2.

      Merci pour ta réponse !

      Pour le moment je souhaite avoir l'approche bourrin et faire une mesure toutes les secondes. Le but du jeu c'est d'avoir un nombre important (le plus précis possible) de mesures sur la latence de plusieurs équipements. L'objectif est de déterminer à quel moment de la journée des latences apparaissent sur le réseau.
      Pour ce qui est du script, je suis dessus.. non sans mal.. :)

      • [^] # Re: Toutes les secondes ?

        Posté par  (site Web personnel) . Évalué à 5.

        Voila un script vite fait en PHP, il faut le nommer check_address.php (car il s'auto-lance pour chaque mesure) :

        <?php
        // check_address.php
        
        function latence($host, $port = 7, $timeout = 10) {
            $ts = microtime(true);
            $f = @fsockopen($host, $port, $errno, $errstr, $timeout);
            $result = microtime(true) - $ts;
            if (! $f) {
                $result = $timeout;
            } else {
                fclose($f);
            }
            return round($result * 1000, 0);
        }
        
        if (! isset($argv[1]) || ! isset($argv[2])) {
            // *******************************************************
            // daemon principal -> lance les pings toutes les secondes
            // *******************************************************
            $list_address = @file_get_contents("./list_address");
            $t_ip = explode("\n", $list_address);
            // nettoyage
            for ($i = 0; $i < count($t_ip); $i++) {
                $t_ip[$i] = trim($t_ip[$i]);
                if ($t_ip[$i] == "") unset($t_ip[$i]);
            }
        
            $time = time();
            while (true) {   // boucle infinie, il faudra killer le process pour terminer le programme
                while ($time == time()) usleep(10);
                $time = time();
                // lancement des mesures
                foreach ($t_ip as $ip) {
                    echo date("Y-m-d H:i:s", $time)." : Mesure de $ip\n";
                    system("php check_address.php ".escapeshellarg($ip)." $time > /dev/null 2> /dev/null &");
                }
            }
            exit();
        } else {
            // **********************************************************************
            // programme appelé par le daemon principal -> mesure latence de cette IP
            // **********************************************************************
            $ip = trim($argv[1]);
            $time = (int) $argv[2];
            // mesure de la latence de cette IP
            $latence = latence($ip);
            // enregistrement de la mesure dans ./jour/ip
            $jour = date("Y-m-d", $time);
            if (! is_dir("./$jour")) mkdir("./$jour");
            if ($f = @fopen("./$jour/$ip", "a")) {
                fputs($f, date("H:i:s", $time)." ".$latence."ms\n");
                fclose($f);
            }
        }
        
        ?>

        La latence est mesurée en faisant un fsockopen sur le port 7. On peut aussi facilement faire du vrai ICMP avec socket_connect et consorts si besoin (à voir ta définition de "latence").
        Le timeout est à 1s par defaut, pour éviter d'engorger la machine avec des process forkés qui se termineraient plus lentement qu'ils ne sont lancés, mais tu peux l'augmenter si tu surveilles un peu tout ça en cours d'execution.
        Si tu surveilles beaucoup beaucoup d'IP, faut voir aussi si la machine suit le rythme.

        • [^] # Re: Toutes les secondes ?

          Posté par  . Évalué à 1.

          Merci bien pour ce script ! Pour l'utilisation, nous sommes d'accord qu'il faut que j'ai mon fichier avec ma liste d'IP appelé list_address et pour l'exécution je l'exécute avec : php check_latency.php ?
          J'ai bien mon dossier avec la date et pour chaque IP, un fichier que se créé. C'est parfait. Seulement l'indication du temps de réponse est erronée (toujours à 1000ms). De plus, si je check une IP qui ne correspond à aucune machine UP, j'ai encore 1000ms comme indication. Pour le moment, j'ai fais un test avec 3 IP -> 1 IP UP, 1 IP UP que j'ai DOWN et 1 IP DOWN. Tous mes fichiers sont remplis de 1000ms.
          Peux-tu me préciser quel est l'intérêt d'interroger le port 7 et de ne pas faire un ICMP classique ?

          Encore une fois merci pour ton aide !

          • [^] # Re: Toutes les secondes ?

            Posté par  (site Web personnel) . Évalué à 1. Dernière modification le 05/09/21 à 19:02.

            Donc je suppose que tes serveurs ne repondent pas sur le port 7. J'ai un routeur comme ça chez moi qui ne repond pas sur le port 7 aussi.
            Quand l'iP ne répond pas, le script met le timeout comme réponse.

            J'en ai fait un script bien plus complet là : https://xulops.net/forge/latencycheck.php
            Tu pourras changer le port, voir utiliser d'autres méthodes de mesure de la lantence (en simulant un ping ICMP en PHP, voire en utilisant la commande ping de la distro).

            • [^] # Re: Toutes les secondes ?

              Posté par  . Évalué à 1.

              Yes, parfait ! Le script fonctionne bien avec la méthode ICMP. Merci pour le partage !
              Je peux ajouter le code pour que les fichiers s'enregistrent correctement avec le nommage que je souhaite ?

                  // enregistrement de la mesure dans ./jour/ip
                  $jour = date("Y-m-d", $time);
                  if (! is_dir("./$jour")) mkdir("./$jour");
                  if ($f = @fopen("./$jour/$ip", "a")) {
                      fputs($f, date("H:i:s", $time)." ".$latence."ms\n");
                      fclose($f);
              • [^] # Re: Toutes les secondes ?

                Posté par  (site Web personnel) . Évalué à 1.

                Je viens de mettre en ligne une version 1.1 qui permet de modifier le format du nom du fichier de sortie. Tu peux donc le télécharger et le lancer par la commande suivante :

                sudo php latencycheck.php -d 1 -m icmp -f list_address -o %DATE/%IP
                
                • [^] # Re: Toutes les secondes ?

                  Posté par  . Évalué à 1.

                  Merci beaucoup pour ton aide et ta réactivité !
                  Le script fonctionne parfaitement.

  • # man ping

    Posté par  . Évalué à 8.

    Quand tu pinges une adresse, par défaut le requête est effectuée toutes les secondes (à vérifier, ta distribution pouvant avoir compilé avec d'autres valeurs) et tu peut changer ce délai avec -i $secondes
    Tu as également -W $millisecondes pour indiquer le délai d'attente de réponse (attention que les paquets qui arrivent hors délais sont marqués comme non répondu mais comptés comme répondus dans les statistiques finales.) À cela on peut rajouter -t $secondes (pour arrêter la commande au bout du temps indiqué) ou -c $entier (pour arrêter la commande après l'envoie de nombre de paquets indiqué) etc. (-o par exemple dans certaines implémentations.)
    Dans un contexte de script, il est aussi intéressant de regarder -q et -Q, ainsi que -n. En tout cas il ne faut pas bêtement rediriger dans un fichier.

    Maintenant, quel est le vrai besoin ? Réinventer ce que la supervision fait très bien ? Surcharger le serveur en l'occupant à répondre aux pingues ?

    “It is seldom that liberty of any kind is lost all at once.” ― David Hume

    • [^] # Re: man ping

      Posté par  . Évalué à 1.

      Merci pour ta réponse. Le vrai besoin est le suivant, j'ai un LAN qui accède à des ressources distantes sur un autre LAN. Il y a des problèmes de lenteur et de perte de paquet régulier entre ces deux réseaux. Il semble que le problème provienne directement du LAN qui demande l'accès aux ressources, puisque le réseau est instable (ms qui varient beaucoup) et des perte de paquet en effectuant des pings entre deux machines de ce même réseau.
      Le besoin est le suivant, générer des traces des résultats des pings toutes les secondes pour que les admins de ce réseau puissent avoir plus d'informations. Le but est que lorsque l'on me demande si le lundi 9 Janvier (date random) à 9h52 le réseau à saturé, je puisse répondre oui ou non avec les temps de réponses à l'appui.
      Je devrais peut être préciser que je suis alternant et qu'on m'a donné cette mission. Donc j'apprends en essayant d'avoir la meilleure approche possible.

      • [^] # Re: man ping

        Posté par  . Évalué à 2. Dernière modification le 06/09/21 à 05:28.

        Si c'est pour apprendre (ce que je comprends de mission d'alternance) alors tu peux regarder les différentes options de ping comme je l'ai mentionné. Une fois que tu as choisi les options qui te conviennent, tu pourras ensuite boucler sur la commande avec ta liste d'adresses.
        Petit bémol, la boucle for du shell POSIX (je présume que tu vas utiliser bash dans un premier temps) sera séquentielle… Mais l'étape suivante sera d'étudier la parallélisation avec un script shell (c'est faisable mais pas trivial ni courant, et sinon y a une commande dédiée…)
        Une fois fini tu pourras demander de l'aide pour améliorer ton script ou si tu rencontre un problème.

        Après ça, dans un second temps (après avoir joué avec les options de la commande, ce qui te permettra d'en avoir une meilleure connaissance, et après avoir fait un peu de scripting) tu pourra jeter un œil à fping qui fait déjà le taf. => cf. eromang.zataz.com par exemple.
        C'est intégré dans SmokePing qui va sauvegarder cette surveillance (quasiment toutes les secondes) dans une base temporelle (RRD) et te générer des graphs… Dans le même registre, sans le stockage, il y a gping aussi.

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: man ping

          Posté par  . Évalué à 1.

          Oui, exact.

          Maintenant, je pense qu'il peut jouer sur une fourchette de 5 secondes.
          Si on lui demande si ça a saturé a 12:52, il suffit de regarder le dernier le ping d'avant et d'après pour avoir une réponse.

          Mais honnêtement je tenterais une approche multithreads en python

          • [^] # Re: man ping

            Posté par  . Évalué à 2.

            J'ai suggéré parallel via un lien :-) L'étape suivante peut être en effet d'utiliser des langages de scripting plus avancés (Python, Ruby, PHP, PERL, AWK, TCL, etc.) C'est toujours formateur d'envisager plusieurs solutions/approches et dans plusieurs langages.
            Et s'il assez de temps et de ressource, envisager même de refaire le bousin (Rust, Go, Java, C++, etc.) sans tricher (i.e. consulter les sources de fping avant d'avoir fini)

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

            • [^] # Re: man ping

              Posté par  . Évalué à 1.

              Entièrement en phase avec ce que vous dites. Dans un premier temps l’objectif de mon poste est de trouver une solution rapidement, mais je vais creuser le sujet par la suite. J'avais repérer fping effectivement. Il n'y a pas assez d'heures dans une journée..

  • # smokeping

    Posté par  . Évalué à 5.

    Bonjour,

    Est-ce que tu connais le projet smokeping ?
    Après ça dépend si tu veux une interface web. Mais cela devrait répondre à ta problématique.

    Bonne journée.

    • [^] # Re: smokeping

      Posté par  . Évalué à 1.

      Bonjour,

      Effectivement smokeping pourrait être une solution. Cependant, je supervise déjà ces équipements avec Centreon. La problématique avec ces outils c'est qu'on ne peux pas faire de check toutes les secondes par exemple. Il y a un mimnimum au niveau des timing qui est trop élevé pour l'usage que je souhaite (même si effectivement 1 seconde c'est overkill).

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.