0

我一直在将我的脚本用于 unix 服务器,并且运行良好。但是,当我使用相同的脚本(有一些小的命令更改)连接到 HP Procurve 开关时,脚本崩溃并出现错误。部分脚本如下:

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(address, username=userna, password=passwd)

stdin,stdout,stderr= ssh.exec_command("show ver")

for line in stdout:
    print '... ' + line.strip('\n')

ssh.close()

这给出了错误

Traceback (most recent call last):
File "C:/Users/kucar/Desktop/my_python/switchmodel", line 34, in <module>
stdin,stdout,stderr= ssh.exec_command("show ver")
File "C:\Python27\lib\site-packages\paramiko\client.py", line 379, in exec_command
chan.exec_command(command)
File "C:\Python27\lib\site-packages\paramiko\channel.py", line 218, in exec_command
self._wait_for_event()
File "C:\Python27\lib\site-packages\paramiko\channel.py", line 1122, in _wait_for_event
raise e
SSHException: Channel closed.

我在网上发现了类似的投诉,但似乎根本没有提供解决方案。Switch 对 ssh 是开放的,并且可以与 putty 一起正常工作。感谢您提供任何可以帮助我的想法。我无法为 100 台交换机手动执行“show ver”命令。

4

3 回答 3

3

正如上面提到的@dobbo,您必须在通道上执行 invoke_shell() 以便您可以执行多个命令。此外,HP ProCurve 在输出中具有 ANSI 转义码,因此您必须将其去掉。最后,HP ProCurve 会发出“按任意键继续”消息,至少在某些设备上您必须通过该消息。

我在这个库中有一个 HP ProCurve 处理程序https://github.com/ktbyers/netmiko

将 device_type 设置为“hp_procurve”。

Exscript 也有某种 ProCurve 处理程序,尽管我还没有深入研究它以使其工作。

于 2015-06-02T02:07:23.040 回答
1

我在使用 ssh 服务器连接到我的三星 s4 手机时也有同样的经历。我连接到 SUSE VM 或 Rasperry Pi 没有问题,还尝试了 MobaXterm(上周 putty 如此)。

我还没有找到答案,但会分享我的研究。

我查看了源代码并在 channel.py 中找到了第 1122 行(复制如下)。

使用我的手机(可能还有您的 HP 交换机),我注意到根本没有登录消息或 MOTD,并且在退出(使用 putty/mobaXterm)时,会话没有正确结束。

在其他一些阅读中,我发现 parameko 不再从作者那里得到太多支持,但其他人正在努力将其移植到 python 3x。

这是我找到的源代码。

def _wait_for_send_window(self, size):
    """
    (You are already holding the lock.)
    Wait for the send window to open up, and allocate up to C{size} bytes
    for transmission.  If no space opens up before the timeout, a timeout
    exception is raised.  Returns the number of bytes available to send
    (may be less than requested).
    """
    # you are already holding the lock
    if self.closed or self.eof_sent:
        return 0
    if self.out_window_size == 0:
        # should we block?
        if self.timeout == 0.0:
            raise socket.timeout()
        # loop here in case we get woken up but a different thread has filled the buffer
        timeout = self.timeout
        while self.out_window_size == 0:
            if self.closed or self.eof_sent:
                return 0
            then = time.time()
            self.out_buffer_cv.wait(timeout)
            if timeout != None:
                timeout -= time.time() - then
                if timeout <= 0.0:
                    raise socket.timeout()
    # we have some window to squeeze into
于 2013-08-17T09:51:12.207 回答
1

似乎如果您不清理连接缓冲区,Paramiko 在使用 HP Procurves 时会发疯。首先,您需要调用一个 shell,否则 Paramiko 将在第一个命令之后简单地断开连接(正常行为,但令人困惑)。

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(switch_ip, username=switch_user, password=switch_pass,look_for_keys=False)
conn = ssh.invoke_shell()
recieveData() # <-- see below

实际处理数据很重要,据我所知,在要求 Paramiko 处理数据之前,您需要确保 Paramiko 确实收到了所有数据。我通过使用以下函数来做到这一点。您可以根据需要调整睡眠,在某些情况下 0.050 可以正常工作。

def recieveData():
    tCheck = 0
    while not conn.recv_ready():
        time.sleep(1)
        tCheck+=1
        if tCheck >=10:
            print "time out"
    cleanThatStuffUp(conn.recv(1024)) # <-- see below

这是返回到您的 ssh 客户端的垃圾的示例。

[1;24r[24;1H[24;1H[2K[24;1H[?25h[24;1H[24;1HProCurve Switch 2650# [24;1H[24;23H[24;1H[?5h[24;23H[24;23Hconfigure[24;23H[?25h[24;32H[24;0HE[24;1H[24;32H[24;1H[2K[24;1H[?5h[24;1H[1;24r[24;1H[1;24r[24;1H[24;1H[2K[24;1H[?25h[24;1H[24;1H

在每个“[”之前还有退出代码要处理。因此,为了解决这个问题,我想出了一些正则表达式来清理所有这些“东西”。

procurve_re1 = re.compile(r'(\[\d+[HKJ])|(\[\?\d+[hl])|(\[\d+)|(\;\d+\w?)')
procurve_re2 = re.compile(r'([E]\b)')
procurve_re3 = re.compile(ur'[\u001B]+') #remove stupid escapes

def cleanThatStuffUp(message):
   message = procurve_re1.sub("", message)
   message = procurve_re2.sub("", message)
   message = procurve_re3.sub("", message)
   print message

现在您可以开始输入命令,只需确保每次使用recieveData() 清除缓冲区即可。

conn.send("\n") # Get past "Press any key"
recieveData()
于 2014-12-13T08:07:54.567 回答