Python 脚本化ssh命令有时会无限期挂起,服务器处于活动状态并接受连接

Python 脚本化ssh命令有时会无限期挂起,服务器处于活动状态并接受连接,python,linux,ssh,Python,Linux,Ssh,我正在自动化一些在云中运行的测试(具体来说) 我配置VM,然后使用ssh运行许多设置步骤 有时候宋承宪会无限期地被绞死,我一辈子都不知道为什么 最初我使用了,但从2015年开始我发现这个问题仍然没有解决,所以我决定改为通过 创建VM后,需要一段时间才能启动,sshd也需要一段时间才能开始侦听。因此,我首先通过ssh在一个循环中运行命令true,直到它成功: retries = 6 while True: # just run 'true' on the remove server so

我正在自动化一些在云中运行的测试(具体来说)

我配置VM,然后使用ssh运行许多设置步骤

有时候宋承宪会无限期地被绞死,我一辈子都不知道为什么

最初我使用了,但从2015年开始我发现这个问题仍然没有解决,所以我决定改为通过

创建VM后,需要一段时间才能启动,sshd也需要一段时间才能开始侦听。因此,我首先通过ssh在一个循环中运行命令
true
,直到它成功:

retries = 6
while True:
    # just run 'true' on the remove server so if it executes successfully we know 
    # sshd is alive and accepting connections
    cmd = ('ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no '
           '-o UserKnownHostsFile=/dev/null {user}@{host} true').format(
           user=user, host=host)
    r = subprocess.run(cmd,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE,
                       shell=True)
    if r.returncode == 0:
        break
    retries -= 1
    if retries == 0:
        raise UnableToConnect()
    time.sleep(10)
成功运行
true
后,我知道服务器处于活动状态并且正在接受ssh连接,因此我可以继续执行设置步骤

def run_cmd(user, host, cmd):
    cmd = ('ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no '
           '-o UserKnownHostsFile=/dev/null {user}@{host} {cmd}').format(
           user=user, host=host, cmd=shlex.quote(cmd))
    r = subprocess.run(cmd,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE,
                       shell=True)
    return {
        'returncode': p.returncode,
        'stdout'    : p.stdout.decode("utf-8").rstrip(),
        'stderr'    : p.stderr.decode("utf-8").rstrip(),
    }
大多数情况下,一切都按预期进行,但有时ssh命令将永远不会返回,无限期地挂起

例如,我需要安装
binutils

run_cmd(user, vm_ip_addr, 'dpkg -s binutils || sudo apt-get install -y binutils')
命令永远不会返回

$ ps -ef | grep ssh
steve 31855 ... 00:00:00 /bin/sh -c ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null fred@123.123.123.123 'dpkg -s binutils || sudo apt-get install -y binutils'
steve 31856 ... 00:00:00 ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null fred@123.123.123.123 dpkg -s binutils || sudo apt-get install -y binutils
我使用
strace
连接到
ssh
命令,它被卡在一个read中:

$ sudo strace -p 31856
strace: Process 31856 attached
read(5, 
(我对
strace
不是很熟练,所以我不确定在这一点上是否还有其他方法可以获得更多信息)

我知道服务器是活动的,因为我能够用ssh连接到服务器上,在运行卡住的命令之前,我的脚本成功地在remove服务器上运行了
true

问题:

  • 为什么这个命令被卡住了
  • 我如何检测和/或防止这种情况

我偶尔也会遇到类似的问题,我强烈怀疑这是因为糟糕的网络质量,错误配置的点连接可能会死掉,但您的连接甚至没有正确断开(数据包会自动消失,并且似乎挂起不动)。长话短说,也许可以尝试设置/使用:
ServerAliveInterval
,查看
manssh\u config
了解详细信息,您也可以通过
-o
在cmdline上传递它;至少检测到情况并终止流程。对于正在进行的连接,没有超时,因此您必须从外部实现watchdog。当您使用ssh在远程系统上调用命令时,本地ssh实例在远程命令完成之前继续运行是正常的。您应该调查发生这种情况时远程服务器上发生的情况。我偶尔会遇到类似的问题,并强烈怀疑这是因为糟糕的网络质量,错误配置到点连接可能会导致死亡,但您的连接甚至没有正确断开(小包静静地消失了,它似乎悬在一个边缘).长话短说,也许可以尝试设置/使用:
ServerAliveInterval
,查看
man ssh\u config
了解详细信息,您也可以通过
-o
在cmdline上传递它;至少可以检测到情况并终止进程。对于正在进行的连接,没有超时,因此您必须从外部实现watchdog。如果您需要e ssh要在远程系统上调用命令,本地ssh实例在远程命令完成之前继续运行是正常的。发生这种情况时,您应该调查远程服务器上发生了什么。