【问题标题】:paramiko ssh client does not work with HP switchesparamiko ssh 客户端不适用于 HP 交换机
【发布时间】:2015-06-02 10:07:23
【问题描述】:

我一直在将我的脚本用于 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”命令。

【问题讨论】:

    标签: python python-2.7 ssh paramiko


    【解决方案1】:

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

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

    将 device_type 设置为“hp_procurve”。

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

    【讨论】:

      【解决方案2】:

      我在使用 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
      

      【讨论】:

        【解决方案3】:

        如果您不清理连接缓冲区,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 处理数据之前,您需要确保它确实收到了所有数据。我通过使用以下函数来做到这一点。您可以根据需要调整睡眠,在某些情况下 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()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-23
          • 2011-04-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-06
          • 1970-01-01
          相关资源
          最近更新 更多