【问题标题】:Paramiko: read from standard output of remotely executed commandParamiko:从远程执行命令的标准输出中读取
【发布时间】:2013-06-12 20:04:49
【问题描述】:

所以我正在使用 paramiko 进行一些基本的 SSH 测试,但我没有将任何输出输入到标准输出中。这是我的代码。

import paramiko
client=paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
com="ls ~/desktop"
client.connect('MyIPAddress',MyPortNumber, username='username', password='password')
output=""
stdin, stdout, stderr = client.exec_command(com)

print "ssh succuessful. Closing connection"
client.close()
print "Connection closed"
stdout=stdout.readlines()
print stdout
print com
for line in stdout:
    output=output+line
if output!="":
    print output
else:
    print "There was no output for this command"

因此,每当我运行此命令时,都会执行命令(如果我执行 cp 之类的操作,则会复制文件),但我总是得到“此命令没有输出”。打印 stdout=stdout.readlines() 时, [] 是输出。此外,如果我在 for 循环中添加一个 print 语句,它永远不会运行。有人可以帮我吗?谢谢!

【问题讨论】:

    标签: python ssh paramiko


    【解决方案1】:

    你在读行之前已经关闭了连接:

    import paramiko
    client=paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    com="ls ~/desktop"
    client.connect('MyIPAddress',MyPortNumber, username='username', password='password')
    output=""
    stdin, stdout, stderr = client.exec_command(com)
    
    print "ssh succuessful. Closing connection"
    stdout=stdout.readlines()
    client.close()
    print "Connection closed"
    
    print stdout
    print com
    for line in stdout:
        output=output+line
    if output!="":
        print output
    else:
        print "There was no output for this command"
    

    【讨论】:

    • 呵呵,没想到。谢谢!
    • @jabaldonedo 我已经在我的项目中尝试过这段代码,但我遇到的问题是我通过 SSH 登录,当它到达任何 stdout.read() 行时它会挂起。就像使用上面的代码一样,它会到达print "ssh successful. Closing connection" 并停止。我什至无法按CTRL+C 退出。似乎无法找到解决此问题的方法。
    • 确实,这段代码可能会挂起,如果该命令也产生错误输出,请参阅Paramiko ssh die/hang with big output
    【解决方案2】:

    *交互示例: ====第 1 部分,这显示了服务器中的 sh 输出,末尾是 ">" 需要一些输入来继续或退出 ======

    selilsosx045:uecontrol-CXC_173_6456-R32A01 lteue$ ./uecontrol.sh -host localhost UE 控制:使用以下命令启动 UE 控制: UE控制:java -Dlogdir= -Duecontrol.configdir=./etc -jar ./server/server-R32A01.jar -host localhost 从文件 /Users/lteue/Downloads/uecontrol-CXC_173_6456-R32A01/etc/uecontrol.properties 加载属性 向主机 localhost 启动远程 CLI 输入命令 Q 退出 CLI,或者输入命令 HELP 获取有关可用命令的信息。 CLI 已准备好输入。 uec>

    ===========带有 peramiko 的 Pyhton 代码 ============*

    试试下面的方法:while not stdout.channel.exit_status_ready():

    def shCommand(server_list):
    server_IP = server_list[0]
    username  = server_list[1]
    password  = server_list[2]
    
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(server_IP,22,username, password)strong text
    
    commandList = ['list \n']
    alldata = getUeInfo(ssh,commandList)
    ssh.close()
    
    def getUeInfo(ssh,commandList):
    data_buffer = ""
    num_of_input = 0
    stdin, stdout, stderr = ssh.exec_command('cmd')
    while not stdout.channel.exit_status_ready():
       solo_line = ""        
    
       if stdout.channel.recv_ready():
    
          solo_line = stdout.channel.recv(1024)  # Retrieve the first 1024 bytes
          data_buffer += solo_line               
    
    
       if(cmp(solo_line,'uec> ') ==0 ):    #len of solo should be 5 ,
         if num_of_input == 0 :
          data_buffer = ""    
          for cmd in commandList :
           #print cmd
           stdin.channel.send(cmd)
          num_of_input += 1
         if num_of_input == 1 :
          stdin.channel.send('q \n') 
          num_of_input += 1
    
    return data_buffer 
    

    【讨论】:

      【解决方案3】:
      # Program to print the output in console/interpreter/shell in runtime without using stdout.
      
       import paramiko
       import xlrd
       import time
      
       ssh = paramiko.SSHClient()
       ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      
       loc = ('/Users/harshgow/Documents/PYTHON_WORK/labcred.xlsx')
       wo = xlrd.open_workbook(loc)
       sheet = wo.sheet_by_index(0)
       Host = sheet.cell_value(0, 1)
       Port = int(sheet.cell_value(3, 1))
       User = sheet.cell_value(1, 1)
       Pass = sheet.cell_value(2, 1)
      
       def details(Host, Port, User, Pass):
             time.sleep(2)
      
             ssh.connect(Host, Port, User, Pass)
             print('connected to ip ', Host)
      
             stdin = ssh.exec_command("")
             remote_conn = ssh.invoke_shell()
             print("Interactive SSH session established")
      
             output = remote_conn.recv(1000)
             remote_conn.send("\n")
             remote_conn.send("xstatus Cameras\n")
      
             time.sleep(5)
             output = remote_conn.recv(10000)
             print(output)
      
       details(Host, Port, User, Pass)
      
      

      【讨论】:

      • 我使用您的方法进入交互式菜单。我想输入“R”并按 Enter,但 remote_conn.send("R\n") 什么也没做。外壳没有采用“R”。我可以在这里做什么?执行 stdin.write("R") 返回'元组没有方法写入'
      【解决方案4】:

      正如@jabaldonedo 所说,您在阅读stdout 之前关闭了您的SSHClient 连接。 SSHClient 可以用作上下文管理器。使用 SSHClient 作为上下文管理器有助于防止您在 ssh 连接关闭后尝试访问 stdoutstderr。 Python3 语法生成的代码如下所示:

      from paramiko import AutoAddPolicy, SSHClient
      
      with SSHClient() as client:
          client.set_missing_host_key_policy(AutoAddPolicy)
          client.connect(
              'MyIPAddress',
              MyPortNumber, 
              username='username', 
              password='password'
          )
      
          com = "ls ~/desktop"
          stdin, stdout, stderr = client.exec_command(com)
      
          output = ''
          for line in stdout.readlines()
              output += line
      
      if output:
          print(output)
      else:
          print("There was no output for this command")
      

      【讨论】:

      • 好的,但是您的代码仍然遇到与@jabaldonedo 的代码相同的死锁问题。
      • 这是什么死锁问题?读取 stdout 时连接仍处于打开状态,并且 SSHClient.__exit__ 将负责在 with 块末尾关闭连接。
      • 我已将评论中的问题与@jabaldonedo 的答案联系起来。如果您需要重复,这里是:Paramiko ssh die/hang with big output.
      【解决方案5】:

      如果命令也产生错误输出,则接受的答案中的代码可能会挂起。见Paramiko ssh die/hang with big output

      如果您不介意合并stdoutstderr,一个简单的解决方案是使用Channel.set_combine_stderr 将它们组合成一个流:

      stdin, stdout, stderr = client.exec_command(command)
      stdout.channel.set_combine_stderr(True)
      output = stdout.readlines()
      

      如果您需要单独读取输出,请参阅Run multiple commands in different SSH servers in parallel using Python Paramiko

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多