want to create a python script which checks if a server on a server is up or not. Rather if a server is up or not I want to catch that result in a file. In the end if a server is down then I want to receive an email.
I use the tutorial https://linuxhint.com/python-server-monitoring-script/ to start creating the python file with the below result.
When I execute the python file I get the below error. I not really familiar with working classes. So I hope you can help me out here.
When execute the below code i get the error you see below. And only the first server is checked. Can you please help me ?
PREVIOUS RESULT
$ C:/Users/.../AppData/Local/Programs/Python/Python38/python.exe c:/Users/.../Documents/git/CV%20Reader%20FastAPI/CheckServer.py
1
('MyServernamae1 is up. On Port 80 with plain', True, <built-in method now of type object at 0x00007FFB92A8B530>)
0
Traceback (most recent call last):
File "c:/Users/.../Documents/git/CV%20Reader%20FastAPI/CheckServer.py", line 84, in <module>
print(server.history[-1])
IndexError: list index out of range
CURRENT RESULT Based on the given solution of 'Kite' i update the code and get the following result. I get for some of the servers result and some are skipped. I expect for every server a result.
AzureAD+....@ToolingDesktop MINGW64 ~/Documents/git/CV%20Reader%20FastAPI (master)
$ C:/Users/.../AppData/Local/Programs/Python/Python38/python.exe c:/Users/.../Documents/git/CV%20Reader%20FastAPI/CheckServer.py
5
('185.104.29.80 is up. On Port 80 with plain', True, datetime.datetime(2021, 10, 17, 16, 9, 31, 955477))
3
('No Clue??: [WinError 10061] No connection could be made because the target machine actively refused it', False, datetime.datetime(2021, 10, 17, 16, 9, 31, 985540))
Expected Result
I expect for every server a result (good or bad)!
This is the result from the https://linuxhint.com/python-server-monitoring-script/ site. I expect from the a response if the server is up or not.
CODE UPDATE (BASED ON GIVEN SOLUTION)
from os import system
import socket
import ssl
import pickle
from datetime import datetime, time
import subprocess
import platform
class Server():
def __init__(self, name, port, connection, priority):
self.name = name
self.port = port
self.connection = connection
self.priority = priority
self.history = []
self.alert = False
def checkConnection(self):
msg = ""
succes = False
now = datetime.now()
try:
if self.connection == "plain":
socket.create_connection((self.name,self.port),timeout=10)
msg = f"{self.name} is up. On Port {self.port} with {self.connection}"
succes = True
self.alert = False
elif self.connection == "ssl":
ssl.wrap_socket(socket.create_connection((self.name,self.port),timeout=10))
msg = f"{self.name} is up. On Port {self.port} with {self.connection}"
succes = True
self.alert = False
else:
if self.ping():
msg = f"{self.name} Timout on Port {self.port} with {self.connection}"
succes = True
self.alert = False
except socket.timeout:
msg = f"{self.name} is Down. On Port {self.port}"
succes = False
alert = True
except Exception as e:
msg = f"No Clue??: {e}"
if succes == False and self.alert == False:
# Send Alert
self.alert = True
# email_alert(self.name,f"{msg}\n{now}","[email protected]")
self.create_history(msg,succes,now)
def ping(self):
try:
output = subprocess.check_output("ping - {} 1 {}".format('n' if platform.system.lower() == 'windowns' else 'c', self.name), shell = True, universal_newlines = True)
if 'unreachable' in output:
return False
else:
return True
except Exception:
return False
def create_history(self,msg,succes,now):
history_max = 100
self.history.append((msg,succes,now))
while len(self.history) > history_max:
self.history.pop(0)
if __name__ == "__main__":
try:
servers = pickle.load(open("servers.pickle","rb"))
except:
servers = [
Server("185.104.29.80",80,"plain","high"),
Server("34.91.11.178",5001,"plain","high"),
Server("reddit.com",80,"plain","high"),
Server("msn.com",80,"plain","high"),
Server("smtp.gmail.com",465,"ssl","high")
]
for server in servers:
server.checkConnection()
print(len(server.history))
print(server.history[-1])
pickle.dump(servers,open("servers.pickle","wb"))
There are few issues with your code, I thought you had followed the tutorial as is but missed few minute things like below.
Firstly, the loading from pickle is not done properly. As it is with try/except block, it doesn't throw any error and it is the main issue.
#this is wrong
servers.pickle.load(open("servers.pickle","rb"))
#it should be like below
servers = pickle.load(open("servers.pickle","rb"))
Secondly, if you want the output to have visible datetime
#this just says as some object
now = datetime.now
#this gives the proper output
now = datetime.now()
Thirdly, why did you combine the email alert logic with other if/elif
blocks only in try
block. It should be added at the end of try/except
blocks. (Logical issue)
Fourthly, This is what makes the list index out of range
issue. In the checkConnection()
last except
block just says pass
, which is very bad and if anything hits there, nothing is added in history too. So, I added the self.create_history()
call as common for all try/except
blocks and updated the last except
to catch the other exceptions like Connection refused
, Temporary failure in name resolution
etc., instead of just pass
and this adds something or the other in the history
.
Please find my updated code below.
from os import system
import socket
import ssl
import pickle
from datetime import datetime, time
import subprocess
import platform
class Server():
def __init__(self, name, port, connection, priority):
self.name = name
self.port = port
self.connection = connection
self.priority = priority
self.history = []
self.alert = False
def checkConnection(self):
msg = ""
succes = False
now = datetime.now()
try:
if self.connection == "plain":
socket.create_connection((self.name,self.port),timeout=10)
msg = f"{self.name} is up. On Port {self.port} with {self.connection}"
succes = True
self.alert = False
elif self.connection == "ssl":
ssl.wrap_socket(socket.create_connection((self.name,self.port),timeout=10))
msg = f"{self.name} is up. On Port {self.port} with {self.connection}"
succes = True
self.alert = False
else:
if self.ping():
msg = f"{self.name} Timout on Port {self.port} with {self.connection}"
succes = True
self.alert = False
except socket.timeout:
msg = f"{self.name} is Down. On Port {self.port}"
succes = False
alert = True
except Exception as e:
msg = f"No Clue??: {e}"
if succes == False and self.alert == False:
# Send Alert
self.alert = True
# email_alert(self.name,f"{msg}\n{now}","[email protected]")
self.create_history(msg,succes,now)
def ping(self):
try:
output = subprocess.check_output("ping - {} 1 {}".format('n' if platform.system.lower() == 'windowns' else 'c', self.name), shell = True, universal_newlines = True)
if 'unreachable' in output:
return False
else:
return True
except Exception:
return False
def create_history(self,msg,succes,now):
history_max = 100
self.history.append((msg,succes,now))
while len(self.history) > history_max:
self.history.pop(0)
if __name__ == "__main__":
try:
servers = pickle.load(open("servers.pickle","rb"))
except:
servers = [
Server("185.104.29.80",80,"plain","high"),
Server("34.91.11.178",5001,"plain","high"),
Server("reddit.com",80,"plain","high"),
Server("msn.com",80,"plain","high"),
Server("smtp.gmail.com",465,"ssl","high")
]
for server in servers:
server.checkConnection()
print(len(server.history))
print(server.history[-1])
pickle.dump(servers,open("servers.pickle","wb"))
After fixing these above issues, you will have the output like below:
1
('185.104.29.80 is up. On Port 80 with plain', True, datetime.datetime(2021, 10, 17, 15, 3, 47, 153334))
1
('No Clue??: [Errno 111] Connection refused', False, datetime.datetime(2021, 10, 17, 15, 3, 47, 425893))
1
('reddit.com is up. On Port 80 with plain', True, datetime.datetime(2021, 10, 17, 15, 3, 51, 216740))
1
('msn.com is up. On Port 80 with plain', True, datetime.datetime(2021, 10, 17, 15, 3, 51, 342316))
1
('smtp.gmail.com is up. On Port 465 with ssl', True, datetime.datetime(2021, 10, 17, 15, 3, 51, 670267))