【问题标题】:Can't catch multiple exceptions from python3/paramiko无法从 python3/paramiko 捕获多个异常
【发布时间】:2019-12-03 04:27:19
【问题描述】:

在 python3 中,我使用 multiprocessing.Pool 并行运行 paramiko 以连接到子网上的每个 ssh 设备。我遇到了一系列似乎无法捕获的错误。

我在这里放了各种 try/except 语句,但没有一个能捕捉到这个错误。我什至用 try/except 包装了 Pool 设置和语句,但那里没有任何改变。所有 paramiko 的东西都在 try_login 函数中,所以它应该来自那里,但所有这些都在 try/except 中,甚至还有一个通用的 except 应该得到所有东西。

我也尝试过组合导致此输出的异常。

#!/usr/bin/env python3

import paramiko
import socket
import ipaddress

network_address = '192.168.50.0/24'
username = ''
password = ''
timeout = 3
num_threads = 30

def trylogin(ipaddress):
    global username, password
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ipaddress, username=username, password=password, timeout=timeout)
        (stdin, stdout, stderr) = ssh.exec_command('cat /var/serial_number')
        imei = stdout.readline()
        if imei != '': print("[+] {}: Success! Found ".format(ipaddress))
        return [ipaddress, imei]
    except paramiko.AuthenticationException:
        print("[-] {}: Authentication Exception!".format(ipaddress))
    except paramiko.SSHException:
        print("[-] {}: SSH Exception!".format(ipaddress))
    except (paramiko.ssh_exception.SSHException, OSError, EOFError):
        pass
    except EOFError:
        pass
    except OSError:
        pass
    except paramiko.ssh_exception.NoValidConnectionsError:
        pass
    except paramiko.ssh_exception.SSHException:
        pass
    except Exception as e:
        print('caught a new fish')
        print(e)
        pass
    finally:
        try:
            ssh.close()
        except:
            pass
    return

network = ipaddress.ip_network(network_address)
for ipaddr in network.hosts():
    print('Checking {}'.format(str(ipaddr)))
    trylogin(str(ipaddr))

运行时会发生大部分应该发生的事情。但我收到一个错误,显示我认为已处理的两个异常。首先是 OSError,然后是 paramiko.ssh_exception.SSHException。我不明白为什么我不能捕获这些。

$ ./find_ssh.py
[-] 192.168.50.1 trying...
[-] 192.168.50.2 trying...
[-] 192.168.50.3 trying...
[-] 192.168.50.4 trying...
[-] 192.168.50.5 trying...
[-] 192.168.50.6 trying...
[-] 192.168.50.7 trying...
[-] 192.168.50.8 trying...
[-] 192.168.50.9 trying...
[-] 192.168.50.10 trying...
[-] 192.168.50.10: Authentication Exception!
[-] 192.168.50.11 trying...
[-] 192.168.50.12 trying...
[-] 192.168.50.13 trying...
[-] 192.168.50.14 trying...
[-] 192.168.50.14: SSH Exception!
[-] 192.168.50.15 trying...
Exception: Error reading SSH protocol banner[Errno 9] Bad file descriptor
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 2211, in _check_banner
    buf = self.packetizer.readline(timeout)
  File "/usr/local/lib/python3.5/dist-packages/paramiko/packet.py", line 380, in readline
    buf += self._read_timeout(timeout)
  File "/usr/local/lib/python3.5/dist-packages/paramiko/packet.py", line 607, in _read_timeout
    x = self.__socket.recv(128)
OSError: [Errno 9] Bad file descriptor

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 2039, in run
    self._check_banner()
  File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 2216, in _check_banner
    "Error reading SSH protocol banner" + str(e)
paramiko.ssh_exception.SSHException: Error reading SSH protocol banner[Errno 9] Bad file descriptor

[-] 192.168.50.16 trying...
[-] 192.168.50.17 trying...
[-] 192.168.50.18 trying...
[-] 192.168.50.19 trying...
[-] 192.168.50.20 trying...

编辑:修改为删除多处理调用。它更慢但更清晰。

【问题讨论】:

  • 尝试不使用 map (这不会导致错误),而是(也不要使用 list comprehensions)使用旧的 for 循环,并在 trylogin 调用之间添加 print,您会发现事情会变得简单得多。当简单的事情不清楚时,最好远离复杂的事情:)
  • 虽然是个好建议,但它不再买我了。我确实这样做了,但没有新的错误。我添加了一些日志记录以确定导致问题的设备,即 192.168.50.15。当我手动 ssh -vvv 到该设备时,与没有错误的设备相比,我没有看到任何不同的行为。

标签: python python-3.x error-handling try-catch paramiko


【解决方案1】:

这是一个丑陋的解决方法,而不是一个答案,但它使错误消失,这是有用的。

添加行:

paramiko.util.log_to_file("main_paramiko_log.txt", level = "INFO")

这样做的效果是创建了一个包含 paramiko 输出的文件。将级别从 INFO 更改为 WARN 或 ERR 很简单。这个特定的错误系列现在作为错误打印到日志文件中,不再打印到屏幕上。

显然未捕获的错误在 paramiko 中很常见,在他们的 github 上发布了 a variety of related issues,在发布之前我没有意识到。

【讨论】:

  • 非常感谢吉姆,我有同样的问题,这个解决方案对我有用非常适合我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 2020-05-10
相关资源
最近更新 更多