Ping to multiple recipients, and if 90% is NG, determine an error and send an email (Gmail). If ping is OK for the specified number of times in a row, recovery is judged.
The first source is multithreaded, but I don't really understand why it works, so I'm not sure why it works. It's also the wrong source as it definitely has bugs.
The program that should have no bugs is described in the second half. It is not multithreaded, but multiprocessed in the second half. 2016/12/29 Fixed: There was a bug, so I fixed it. Please refer to the comments in the source for details of the latter half of the program.
Then it is the explanation of the wrong source. For the time being, it is import.
import pandas as pd
import smtplib
import os, platform
import threading
Next is the Gmail sending function. When sending Gmail, you need to enable POP access in your account to allow access to insecure apps as well. If you search, you will find a kind commentary with a GUI screen attached, so I will leave the details to you.
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()
Next is the ping function. log is a DataFrame. It doesn't have to be a data frame, but I'm used to it because I'm used to it. There are a lot of arguments to save the ping result, and this is the part I think is dirty.
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
Next is the main function. Sequentially, the result of ping is written in the data frame called log, and each time, when 700 points are traced back from the latest log, if there are 600 or more ping errors, the mail is skipped.
if __name__ == '__main__':
domain_list = ['***address***'] # your favorite address
log = pd.DataFrame(0, index=range(60 * 60), columns=domain_list)
#For the time being, create a large 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):#I feel this is inefficient
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)
The day after I wrote the above source, I thought that multiprocessing would be better, so I rewrote it. I found the dict type useful for the first time.
First, the Gmail sending part is the same. Next, regarding Ping transmission, it has been revised as follows.
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
result is of type dict. Later, we will do multiprocessing. As for ping, subprocess.call seems to be better than os.system, so I am rewriting it without understanding.
Next, the main function is as follows.
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)
#It defines a DataFrame that saves the result after pinging.
while True:
proc = [] #For multiprocessing
result = manager.dict() #Define a dict to share between processes
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()
#Copy the ping result from the dict type result to the log of the DataFrame.
for address in domain_list:
log.ix[current_position, address] = result[address]
#Since the log will continue to be used by spinning around, the current position that contains the latest data
#Depending on the value, dataframe.sum()The range to be aggregated is changed in.
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()
#Similar to the above value, recover with a slightly shorter check range in order to reflect the judgment at the time of ping OK as soon as possible._Calculate value
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)]
#I try to call sendGmail only when the result changes so that the notification email does not fly too much.
#Since the design does not look at the details of the number of ping NGs, only the index is extracted and compared.
#.difference()Does not diff check in both directions, so I connect one-way check with or.
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)
I use pandas because I like pandas, which I'm used to, for log aggregation. For multiprocessing, we needed some sharable data, so we do result = manager.dict () and pass it to the ping function.
Recommended Posts