Yup, I missed it.
Here is a potential solution to your issue. Review and become familiar with it.
This script is an extension of the prior submission. I have incorporated your code for the email notification as a class method and the ping checking code as part of the main loop. I have also added an extra set of variables that keep track of the number of hours that the servers have been down and send those values as part of the Subject heading for easy reference.
I have added a second class ServerPing. It inherits the Server class where the bulk of the work is performed. The ServerPing class serves as the keeper of the main loop.
I have incorporated the time module to add a delay between server pings. The value in seconds is 900. There are 900 seconds in 15 minutes hence the value.
Test it and see if it addresses your issue or modify it to your needs:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import os
import time
server_account = 'MyEmail@outlook.com'
server_password = 'MyPassword'
servers = ('Server1', 'Server2', 'Server3', 'Server4')
class Server:
# Can use a class for server fault checking since variables have persistence
# between method calls
def __init__(self):
# Server fault counters - initialize counts
self.counter1 = 0
self.counter2 = 0
self.counter3 = 0
self.counter4 = 0
# email notification type flag (15 min or hourly)
self.flag1 = 0
self.flag2 = 0
self.flag3 = 0
self.flag4 = 0
# Counts the hours that server 'X' has been down
self.hours_down1 = 0
self.hours_down2 = 0
self.hours_down3 = 0
self.hours_down4 = 0
# Associate flags to servers
self.server_email_flags = {'Server1': self.flag1, 'Server2': self.flag2,
'Server3': self.flag3, 'Server4': self.flag4}
# Associate counters to servers
self.server_status = {'Server1': self.counter1, 'Server2': self.counter2,
'Server3': self.counter3, 'Server4': self.counter4}
# Associate hourly fault counters to servers
self.server_hours_down = {'Server1': self.hours_down1, 'Server2': self.hours_down2,
'Server3': self.hours_down3, 'Server4': self.hours_down4}
# Call method if respond = 1 # This implies a server is down
def server_fault_update(self, server): # Pass current server being checked as argument
self.server_fault_counter(server)
# reset counter for corresponding server
# method called if 'respond' != 1; implies the server is back online and working
def reset_server_counter(self, server):
self.server_status[server] = 0
self.server_email_flags[server] = 0
self.hours_down[server] = 0
def server_fault_counter(self, server):
self.server_status[server] += 1
# Send email 15 minutes after first detecting server going offline.
if self.server_status[server] == 2 and self.server_email_flags[server] == 0:
self.server_email_flags[server] = 1 # Set to '1' so that it doesn't enter here again
self.server_status[server] = 1
self.email_notification(server, 0, False)
# Send email notificatin in hour intervals after first detecting server going offline.
if self.server_status[server] % 4 == 0 and self.server_email_flags[server] == 1:
self.server_status[server] = 0
self.hours_down[server] += 1
self.email_notification(server, 1, self.hours_down[server])
def email_notification(self, server, flag, hours_down):
msg = MIMEMultipart()
if flag == 0:
msg["Subject"] = server + " has been down 15 minutes."
else:
msg["Subject"] = server + " hours down: " + str(hours_down)
msg["From"] = "MyEmail@outlook.com"
msg["To"] = "email1@outlook.com"
body = MIMEText("Server " + server + " is down")
msg.attach(body)
smtp = smtplib.SMTP('smtp.office365.com', 587)
smtp.ehlo()
smtp.starttls()
smtp.login(server_account, server_password)
smtp.sendmail(msg["From"], msg["To"].split(","), msg.as_string())
smtp.quit()
class ServerPing(Server):
def __init__(self):
super().__init__()
def main(self):
try:
while True:
for server in servers:
respond = os.system("ping -n 1 " + server + " > nul")
if respond == 1:
# Increment server offline counter and send notification email if necessary
Server.server_fault_counter(self, server)
else:
# Reset counters and flags
Server.reset_server_counter(self, server)
time.sleep(900) # Wait 15 minutes (900 seconds)
except KeyboardInterrupt:
print('\nExiting server pinging process..')
if __name__ == '__main__':
server_pinging = ServerPing()
server_pinging.main()