重启后无法建立连接

cannot establish connection after reboot

伙计们,

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

目标

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

脚本

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

我将 post 这个作为答案,因为它太长了,无法在评论中解释。

您的代码仍然缺少部分,因为我们不知道您如何调用 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 连接,并且仅在您再次建立有效连接时才离开错误处理程序。

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

这在您的情况下可能有效,也可能无效,因为我们无法从您的代码中得知您在异常后如何重新输入 - 而且根据您的评论,您似乎也不确定。