首页 > 解决方案 > 重启后无法建立连接

问题描述

伙计们,

我在重新启动后尝试重新连接到服务器时遇到了问题。我看到了其他关于类似问题的文章,但我尝试的一切都出现了同样的错误。

目标

重启后自动重新连接到服务器

脚本

ssh_client = SSHClient()
ssh_client.set_missing_host_key_policy(AutoAddPolicy())
ssh_client.connect(hostname=host,port=port, username=user, password=psw)
s = ssh_client.get_transport().open_session()
agent.AgentRequestHandler(s)

         try:
            stdin, stdout, stderr = ssh_client.exec_command(command, get_pty= True)
            get_output(stdout)
            channel = stdout.channel
            stdin.close()
            channel.shutdown_write()
            stdout_chunks = []
            stdout_chunks.append(channel.recv(len(channel.in_buffer)))
            while not channel.closed or channel.recv_ready() or channel.recv_stderr_ready():
                got_chunk = False
                readq, _, _ = select.select([stdout.channel], [], [])
                for c in readq:
                    if c.recv_ready():
                        stdout_chunks.append(channel.recv(len(c.in_buffer)))
                        got_chunk = True
                    if c.recv_stderr_ready():
                        stderr.channel.recv_stderr(len(c.in_stderr_buffer))
                        got_chunk = True
                    if not got_chunk \
                            and channel.exit_status_ready() \
                            and not channel.recv_stderr_ready() \
                            and not channel.recv_ready():
                        channel.shutdown_read()
                        channel.close()
                        break
            stdout.close()
            stderr.close()

        except (ConnectionResetError, SSHException):
            print('Connection died')

错误由 try catch 块缓存:

Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died
Connection died

我在远程服务器上运行的脚本以重启命令结束:

/sbin/shutdown -r now

标签: pythonparamikoreboot

解决方案


我会将其发布为答案,因为它太长而无法在评论中解释。

您的代码仍然缺少部分,因为我们不知道您如何调用 try/except 结构以及捕获异常时会发生什么。但是,如果我可以从您的缩进中猜测是,如果捕获到异常,您将以某种方式重复 try/except。

您似乎依赖逻辑中的通道关闭状态,但有一个 TCP 套接字形式的底层。当您重新启动服务器时,您的通道会死掉,但 TCP 层也会死掉。在您的异常处理中,您需要重新创建它。

我会尝试这样的事情:

try:
    ...
    ...
    ...
    stdout.close()
    stderr.close()
except (...):
    sleep(2)  # to prevent a busyloop when your server is rebooting      
    try:
        ssh_client.close()  # Close the connection just in case it is alive
    except:
        pass    # We do not care if it succeeds or fails
    counter = 0     # optional
    while True:
        sleep(2)    # to prevent a busyloop when your server is rebooting
        counter += 1
        if counter > X:
            print("server permanently down, exiting")
            exit (1)
        try:
            ssh_client.connect(hostname=host,port=port, username=user, password=psw)
            s = ssh_client.get_transport().open_session()
            break    # We have a liftoff
        except:
            pass     # Server not responding yet. Try again. 

(上面的代码我没有测试,只是写在这里给出思路,可能有错别字)

您可以忽略计数器部分。如果服务器长期停机,我通常使用计数器来防止程序尝试直到奶牛回家。如果您想继续尝试,请删除这些。如果您使用它们,只需将 X 设置得足够高,以允许服务器有足够的时间重新启动,然后再重新启动一些。

关键部分是在发生错误后重新创建您的 TCP 连接,并且仅在您再次有工作连接时才离开错误处理程序。

我们会尝试关闭现有连接,以防万一它仍然存在,以避免在连接断开没有问题的情况下耗尽服务器资源,但我们不关心它是成功还是失败。然后我们从头开始重新创建连接。

这可能适用于您的情况,也可能不适用,因为我们从您的代码中不知道您如何在出现异常后重新输入 - 而且您似乎也不确定是否基于您的评论。


推荐阅读