【问题标题】:How can you get the SSH return code using Paramiko?如何使用 Paramiko 获取 SSH 返回码?
【发布时间】:2011-04-03 12:11:03
【问题描述】:
client = paramiko.SSHClient()
stdin, stdout, stderr = client.exec_command(command)

有没有办法获取命令返回码?

很难解析所有的 stdout/stderr 并知道命令是否成功完成。

【问题讨论】:

    标签: python ssh paramiko


    【解决方案1】:

    SSHClient 是一个简单的包装类,它围绕着 Paramiko 中更底层的功能。 API documentation 列出了 Channel 类上的 recv_exit_status() 方法。

    一个非常简单的演示脚本:

    import paramiko
    import getpass
    
    pw = getpass.getpass()
    
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.WarningPolicy())
    client.connect('127.0.0.1', password=pw)
    
    while True:
        cmd = raw_input("Command to run: ")
        if cmd == "":
            break
        chan = client.get_transport().open_session()
        print "running '%s'" % cmd
        chan.exec_command(cmd)
        print "exit status: %s" % chan.recv_exit_status()
    
    client.close()
    

    其执行示例:

    $ python sshtest.py
    Password: 
    Command to run: true
    running 'true'
    exit status: 0
    Command to run: false
    running 'false'
    exit status: 1
    Command to run: 
    $
    

    【讨论】:

    • 这是一个糟糕的解决方案。请参阅下面的@apdastous 的答案,这要好得多。
    • 虽然您对recv_exit_status 的看法是正确的,但您不能这样使用它,因为代码可能会死锁。您必须在等待命令完成时使用命令输出。见Paramiko ssh die/hang with big output
    【解决方案2】:

    一个更简单的示例,不涉及直接调用“较低级别”通道类(即 - NOT 使用 client.get_transport().open_session() 命令):

    import paramiko
    
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect('blahblah.com')
    
    stdin, stdout, stderr = client.exec_command("uptime")
    print stdout.channel.recv_exit_status()    # status is 0
    
    stdin, stdout, stderr = client.exec_command("oauwhduawhd")
    print stdout.channel.recv_exit_status()    # status is 127
    

    【讨论】:

    • 关于这个例子的 nice 不只是捕获 EXIT(就像问题所问的那样),而是证明您仍然可以获得 STDOUT 和 STDERR。几年前,我被 Paramiko 贫乏的示例代码库所误导(没有不尊重),为了获得 EXIT,我求助于低级别的 transport() 调用。 transport() 似乎迫使您“选择一个”(这可能不是真的,但缺乏示例和教程文档让我相信)......
    • 虽然您对recv_exit_status 的看法是正确的,但您不能这样使用它,因为代码可能会死锁。您必须在等待命令完成时使用命令输出。见Paramiko ssh die/hang with big output
    【解决方案3】:

    就我而言,输出缓冲是问题所在。由于缓冲,应用程序的输出不会以非阻塞方式输出。您可以在此处找到有关如何在不缓冲的情况下打印输出的答案:Disable output buffering。简而言之,只需像这样使用 -u 选项运行 python:

    > python -u script.py

    【讨论】:

      【解决方案4】:

      感谢 JanC,我为示例添加了一些修改并在 Python3 中进行了测试,它对我非常有用。

      import paramiko
      import getpass
      
      pw = getpass.getpass()
      
      client = paramiko.SSHClient()
      client.set_missing_host_key_policy(paramiko.WarningPolicy())
      #client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      
      def start():
          try :
              client.connect('127.0.0.1', port=22, username='ubuntu', password=pw)
              return True
          except Exception as e:
              #client.close()
              print(e)
              return False
      
      while start():
          key = True
          cmd = input("Command to run: ")
          if cmd == "":
              break
          chan = client.get_transport().open_session()
          print("running '%s'" % cmd)
          chan.exec_command(cmd)
          while key:
              if chan.recv_ready():
                  print("recv:\n%s" % chan.recv(4096).decode('ascii'))
              if chan.recv_stderr_ready():
                  print("error:\n%s" % chan.recv_stderr(4096).decode('ascii'))
              if chan.exit_status_ready():
                  print("exit status: %s" % chan.recv_exit_status())
                  key = False
                  client.close()
      client.close()
      

      【讨论】:

      • 我们是否在 chan.recv_stderr_ready() 中收到任何错误消息(如果有)? chan.recv_stderr(4096).decode('ascii') 这会返回消息文本吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-05
      • 2011-03-14
      • 2015-10-28
      • 2019-08-04
      • 1970-01-01
      相关资源
      最近更新 更多