Python prickly 列表索引超出范围

Python pickly ListIndexOut of Range

想要创建一个 python 脚本来检查服务器上的服务器是否已启动。相反,如果服务器是否启动,我想在文件中捕获该结果。最后,如果服务器出现故障,那么我想收到一封电子邮件。

我使用教程 https://linuxhint.com/python-server-monitoring-script/ 开始创建具有以下结果的 python 文件。

当我执行 python 文件时,出现以下错误。我不太熟悉工作 类。所以我希望你能在这里帮助我。

当执行下面的代码时,我得到了你在下面看到的错误。并且只检查第一台服务器。你能帮帮我吗?

上次结果

$ 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

当前结果 基于 'Kite' 的给定解决方案,我更新了代码并得到以下结果。我得到了一些服务器结果,有些被跳过了。我希望每个服务器都有一个结果。

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))

预期结果

我希望每个服务器都有一个结果(好或坏)!

这是 https://linuxhint.com/python-server-monitoring-script/ 网站的结果。如果服务器已启动,我希望得到响应。

代码更新(基于给定的解决方案)

  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}","erik.hoeven@gmail.com")
        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"))

您的代码几乎没有问题,我以为您已经按原样按照教程进行操作,但错过了如下几分钟的内容。

首先,pickle 加载不正确。与 try/except 块一样,它不会抛出任何错误,它是 main 问题。

#this is wrong
servers.pickle.load(open("servers.pickle","rb"))
#it should be like below
servers = pickle.load(open("servers.pickle","rb"))

其次,如果您希望输出具有可见的日期时间

#this just says as some object
now = datetime.now
#this gives the proper output
now = datetime.now()

第三,为什么你只在try块中将电子邮件警报逻辑与其他if/elif块结合起来。它应该添加在 try/except 块的末尾。 (逻辑问题)

第四,这就是造成list index out of range问题的原因。在 checkConnection() 最后一个 except 块中只说 pass,这是非常糟糕的,如果有任何东西击中那里,历史中也不会添加任何内容。因此,我添加了对所有 try/except 块通用的 self.create_history() 调用,并更新了最后一个 except 以捕获其他异常,例如 Connection refusedTemporary failure in name resolution 等,而不仅仅是 pass 这会在 history.

中添加一些东西

请在下面找到我更新的代码。

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}","erik.hoeven@gmail.com")
        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"))

解决上述问题后,您将得到如下输出:

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))