问题 优雅的方式来测试SSH可用性


我需要一个Python程序,我用它来轮询远程服务器以获得SSH连接,并在它可用时通知。我目前正在使用paramiko这样做;尝试连接,如果失败,请等待并重试,直到成功或最大重试。这有效,但它有点笨重。 paramiko似乎连接或抛出错误,所以我能看到的唯一方法是使用try / except块,这是坏的,坏的,坏的。这是方法:

def check_ssh(self, ip, user, key_file, initial_wait=0, interval=0, retries=1):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    sleep(initial_wait)

    for x in range(retries):
        try:
            ssh.connect(ip, username=user, key_filename=key_file)
            return True
        except Exception, e:
            print e
            sleep(interval)
    return False

必须有比这更优雅的解决方案。 Paramiko是我选择的SSH库,但我对这里的任何建议持开放态度。

为了澄清,我想避免使用try / except作为控制正常代码执行流程的手段 - 它应该用于捕获实际错误,例如错误的主机密钥,无效的用户等。


8977
2018-01-09 13:30


起源

the only way I could see to do this was with a try/except block which is bad, bad, bad 为什么不好? - David Robinson
抓住你肯定是对的 Exception 不好。但是,捕获paramiko抛出的特定异常并不坏。 - Fredrick Brennan
实际上,但是使用异常处理作为程序流程的手段通常很糟糕,如下: google-styleguide.googlecode.com/svn/trunk/... - nightowl
我没有把实际的例外情况放在一边,因为这本来是一个临时的黑客攻击,加上我很懒!我的问题是,我不想使用try / except来控制程序的正常流程 - 只是为了捕获实际的错误 - nightowl


答案:


正如frb的评论中提到的那样 try ... except block是测试特定服务可用性的好方法。你不应该使用“全能” except 虽然阻止,但将其限制为服务不可用时发生的特定异常。

根据文件, paramiko.SSHClient.connect 可能会抛出不同的异常,具体取决于连接时发生的问题。如果你想抓住所有这些,你的 try ... except 块看起来像这样:

try:
    ssh.connect(ip, username=user, key_filename=key_file)
    return True
except (BadHostKeyException, AuthenticationException, 
        SSHException, socket.error) as e:
    print e
    sleep(interval)

如果这些异常的一部分与您的案例相关,那么只将其放入元组中 except


12
2018-01-09 14:05



我的松弛代码的公平点只指定了一个通用异常:p我确实需要一个try / catch我想像一个糟糕的主机密钥之类的东西,因为这些是实际的错误而不是“服务器还没有启动” - 关键是我做的不希望try / except块控制等待循环(即代码的正常流程)。 - nightowl