[PYTHON] Un script qui envoie un ping au serveur enregistré et envoie un e-mail avec Gmail un certain nombre de fois en cas d'échec

Le ping est envoyé à plusieurs destinations, et lorsque 90% est NG, il est considéré comme une erreur et un e-mail est envoyé (Gmail). Si le ping est OK pour le nombre spécifié de fois de suite, la récupération est jugée.

La première source est multithread, mais je ne comprends pas vraiment pourquoi cela fonctionne, donc je ne sais pas pourquoi cela fonctionne. C'est aussi la mauvaise source car il y a certainement des bugs.

Le programme qui ne devrait avoir aucun bogue est décrit dans la seconde moitié. Ce n'est pas multi-thread, mais multi-traitement dans la seconde moitié. 2016/12/29 Corrigé: Il y avait un bug, donc je l'ai corrigé. Veuillez vous référer aux commentaires dans la source pour plus de détails sur la seconde moitié du programme.

Ensuite, c'est l'explication de la mauvaise source. Pour le moment, c'est l'importation.

import pandas as pd
import smtplib
import os, platform
import threading

Vient ensuite la fonction d'envoi de Gmail. Lors de l'envoi de Gmail, vous devez activer l'accès POP dans votre compte pour autoriser l'accès à des applications moins sécurisées. Si vous recherchez, vous trouverez un commentaire aimable avec un écran GUI attaché, je vous laisse donc les détails.

def sendGmail(text):
    user = '****@gmail.com'  # username
    password = '******'  # password
    to = ['****@gmail.com'] # your favorite mail address
    sub = 'mail title'
    msg = '''From: %s\nTo: %s\nSubject: %s\n\n%s
    ''' % (user, ','.join(to), sub, text)

    server = smtplib.SMTP_SSL("smtp.gmail.com", 465)
    server.ehlo()
    server.login(user, password)
    server.sendmail(user, to, msg)
    server.close()

Vient ensuite la fonction d'envoi de ping. log est un DataFrame. Ce n'est pas forcément un bloc de données, mais j'y suis habitué parce que j'y suis habitué. Il y a beaucoup d'arguments pour enregistrer le résultat du ping, et c'est la partie que je trouve sale.

def ping(address, current_position, log):
    ping_str = '-n 1' if platform.system().lower() == 'windows' else '-c 1'
    response = os.system('ping ' + ping_str + ' ' + address)

    if response == 1:
        log[address][current_position] = 1

Vient ensuite la fonction principale. Séquentiellement, le résultat du ping est écrit dans la trame de données appelée journal et à chaque fois, lorsque 700 points sont retracés à partir du dernier journal, s'il y a 600 erreurs de ping ou plus, le courrier est ignoré.

if __name__ == '__main__':

    domain_list = ['***address***'] # your favorite address

    log = pd.DataFrame(0, index=range(60 * 60), columns=domain_list)
    #Pour le moment, créez un grand DataFrame.
    current_position = 0
    sum_of_seconds = 0

    sendGmail('tool has started.')

    while True:
        text = []
        for address in domain_list:
            p = threading.Thread(target=ping, args=(address, current_position, log))
            p.start()

            sum_error = 0

            for i in range(700):#Je pense que c'est inefficace
                 sum_error += log.ix[current_position - i if current_position >= i else 60 * 15 - (i - current_position), address]

            if sum_error > 600:
                text.append(address)

        if (sum_of_seconds % 600 == 0) and (text != []):
            sendGmail(text)

        current_position += 1
        if current_position >= 60 * 15:
            current_position = 0

        sum_of_seconds += 1
        time.sleep(1)

Le jour après avoir écrit la source ci-dessus, j'ai pensé que le multi-traitement serait mieux, alors je l'ai réécrit. J'ai trouvé le type dict utile pour la première fois.

Tout d'abord, la partie envoi de Gmail est la même. Ensuite, concernant la transmission Ping, il a été révisé comme suit.

import multiprocessing as mp

def ping(address, result):
 ping_str = '-n 1' if platform.system().lower() == 'windows' else '-c 1'
 response = subprocess.call('ping '+ ping_str + ' '+address)

 if response = 1:
  result[address] = 1
 else:
  result[address] = 0

le résultat est de type dict. Plus tard, nous ferons du multi-traitement. En ce qui concerne le ping, subprocess.call semble être meilleur que os.system, donc je le réécris sans comprendre.

Vient ensuite la fonction principale, qui est la suivante.

if __name__ == '__main__':
    manager = mp.Manager()
 
    current_position = 0
    bottom = 60*60
    evaluate_range = 5 # x5
    recover_range = 2 #10
    evaluate_ratio = 0.9
    before_result = pd.Series()
    act_num = 0
 
    domain_list = ['***', '****']
 
    log = pd.DataFrame(0, index=range(bottom), columns=domain_list)
    #Il définit un DataFrame qui enregistre le résultat après le ping.
 
    while True:
        proc = [] #Pour le multi-traitement
        result = manager.dict() #Définir un dict à partager entre les processus
        for address in domain_list:
            p1 = mp.Process(target=ping, args=(address, result,))
            proc.append(p1)
 
        for p1 in proc:
            p1.start()
 
        for p1 in proc:
            p1.join()
 
        #Copiez le résultat du ping du résultat de type dict dans le journal du DataFrame.
        for address in domain_list:
            log.ix[current_position, address] = result[address]

       #Puisque le journal continuera d'être utilisé en tournant, la position actuelle contenant les dernières données
       #En fonction de la valeur, dataframe.sum()La plage à agréger est modifiée dans.
        value = log.ix[current_position-evaluate_range:current_position, :].sum() if current_position >= evaluate_range else \
            log.ix[0:current_position, :].sum() + log.ix[bottom-(evaluate_range-current_position):bottom,:].sum()

        #Similaire à la valeur ci-dessus, récupérez avec une plage de contrôle légèrement plus courte afin de refléter le jugement au moment du ping OK dès que possible._Calculer la valeur
       recover_value = log.ix[current_position-recover_range:current_position, :].sum() if current_position >= recover_range else \
            log.ix[0:current_position, :].sum() + log.ix[bottom-(recover_range-current_position):bottom,:].sum()
        result = value[(value > evaluate_range*evaluate_ratio) & (recover_value != 0)]

        #J'essaie d'appeler sendGmail uniquement lorsque le résultat change pour que le mail de notification ne vole pas trop.
        #Puisque la conception ne regarde pas les détails du nombre de ping NG, seul l'index est extrait et comparé.
        #.difference()Ne vérifie pas le différentiel dans les deux sens, je connecte donc la vérification unidirectionnelle avec ou.
        if not pd.Series().index.equals(result.index.difference(before_result.index)) or not pd.Series().index.equals(before_result.index.difference(result.index)):
            if result.size != 0:
                sendGmail(result.index.str.cat(sep='\n'))
                before_result = result
            else:
                sendGmail('All server are normally operating.')
                before_result = result
 
        current_position += 1
        if current_position > bottom:
            current_position = 0
        time.sleep(1)

J'utilise des pandas parce que j'aime les pandas familiers pour l'agrégation de journaux. J'avais besoin de données partageables pour le multi-traitement, j'ai donc passé result = manager.dict () à la fonction ping.

Recommended Posts

Un script qui envoie un ping au serveur enregistré et envoie un e-mail avec Gmail un certain nombre de fois en cas d'échec
Un serveur qui renvoie le nombre de personnes devant la caméra avec bottle.py et OpenCV
[Art de la coquille] Seulement quand c'est un multiple de 3 et un nombre avec 3 devient stupide
Un simple serveur simulé qui incorpore simplement l'en-tête de la requête HTTP dans le corps de la réponse et le renvoie.
[Python] Précautions lors de la recherche des valeurs maximum et minimum avec un tableau numpy avec un petit nombre d'éléments
Utilisez Ruby et Python pour trouver la probabilité qu'une carte avec un nombre naturel de 1 à 100 soit un multiple de 3 et non un multiple de 5.
J'ai créé un système avec Raspberry Pi qui mesure périodiquement l'indice d'inconfort de la pièce et envoie une notification LINE s'il s'agit d'une valeur dangereuse
J'ai réussi à le faire parce que la coutume de joindre un zip avec un mot de passe à un e-mail et de dire «Je vous enverrai le mot de passe séparément» est gênante.
Un script python qui obtient le nombre de travaux pour une condition spécifiée sur Indeed.com
Un script qui peut effectuer des tests de résistance en fonction du nombre de cœurs CPU
Un système simple qui prend automatiquement des photos avec détection d'objet et l'envoie à LINE
Procédure de génération et d'enregistrement d'un modèle d'apprentissage par machine learning, en faisant un serveur API et en communiquant avec JSON depuis un navigateur
Je n'aime pas être frustré par la sortie de Pokemon Go, j'ai donc créé un script pour détecter la sortie et le tweeter
PGM qui prend la différence de la zone rectangulaire spécifiée de la caméra et adoucit le son lorsque le taux de changement dépasse un certain taux
Lors de l'accès à une URL contenant du japonais (URL japonais) avec python3 avec urllib, elle sera encodée arbitrairement avec html et une erreur se produira, alors notez la solution de contournement
[Python] Un programme qui compte le nombre de vallées
Un script qui prend un instantané d'un volume EBS
Script pour changer la longueur du son avec REAPER
Récupérez la chaîne correspondante dans l'expression régulière et réutilisez-la lors du remplacement sur Python3
À propos du contenu de wscript lors de la création d'un environnement en langage D comme celui avec Waf
[Python] Programmation pour trouver le nombre de a dans une chaîne de caractères qui se répète un nombre spécifié de fois.
Script Python qui peut vérifier l'état du serveur à partir du navigateur
[Python] Un programme pour trouver le nombre de pommes et d'oranges qui peuvent être récoltées