首页 > 解决方案 > 脚本化的 ssh 命令偶尔会无限期挂起,服务器处于活动状态并接受连接

问题描述

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

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

有时 ssh 会无限期地挂起,我终生无法弄清楚原因。

最初我使用paramiko.exec_command,但我发现2015 年的这个问题仍未解决,所以我决定改为尝试通过 vanilla ssh 命令subprocess.run

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

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

我使用附加到ssh命令strace,它被困在阅读中:

$ sudo strace -p 31856
strace: Process 31856 attached
read(5, 

(我不是很熟练,strace所以我不确定此时我是否可以做任何其他事情来获取更多信息)

我知道服务器是活着的,因为我可以 ssh 到它上面,并且在运行卡住的命令之前,我的脚本成功地true在删除服务器上运行。

问题:

标签: pythonlinuxssh

解决方案


推荐阅读