14

so I was working with paramiko for some basic SSH testing and I'm not getting any output into stdout. Heres my code.

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"

So whenever I run this, the command is executed (as seen by if I do something like a cp, the file is copied), but I always get "There was no output for this command". When stdout=stdout.readlines() is printed, [] is the output. In addition, if I add a print statement into the for loop, it never gets run. Could someone help me out here? Thanks!

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
ollien
  • 4,418
  • 9
  • 35
  • 58

5 Answers5

29

You have closed the connection before reading lines:

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
  • 25,822
  • 8
  • 77
  • 77
  • @jabaldonedo I have tried this code with my project, what I am having an issue with is that I SSH in and when it gets to any stdout.read() line it hangs. Like using the above code it gets to `print "ssh successful. Closing connection"` and stops. I can't even CTRL+C to get out. Can't seem to find a fix for this. – tjoenz Jan 07 '14 at 15:42
  • Indeed, this code may hang, if the command produces also error output, see [Paramiko ssh die/hang with big output](https://stackoverflow.com/q/31625788/850848). – Martin Prikryl Oct 15 '20 at 07:15
5

The code in the accepted answer may hang, if the command produces also an error output. See Paramiko ssh die/hang with big output.

An easy solution, if you do not mind merging stdout and stderr, is to combine them into one stream using Channel.set_combine_stderr:

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

If you need to read the outputs separately, see Run multiple commands in different SSH servers in parallel using Python Paramiko.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
2

*Interactive example : ====Part 1, this show the sh output in server ,at the end of is ">" need some input to continual or exit ======

selilsosx045:uecontrol-CXC_173_6456-R32A01 lteue$ ./uecontrol.sh -host localhost UE Control:Start UE control using: UE Control:java -Dlogdir= -Duecontrol.configdir=./etc -jar ./server/server-R32A01.jar -host localhost Loading properties from file /Users/lteue/Downloads/uecontrol-CXC_173_6456-R32A01/etc/uecontrol.properties Starting remote CLI towards host localhost Enter the command Q to exit the CLI, or the command HELP to get information on available commands. The CLI is ready for input. uec>

===========Pyhton code with peramiko ============*

Try below method : 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 
kevin yu
  • 89
  • 1
  • 3
1

As @jabaldonedo said you closed your SSHClient connection before reading the stdout. SSHClient can be used as a context manager. Using the SSHClient as a context manager helps prevent you from trying to access stdout and stderr after the ssh connection is closed. The resulting code in Python3 syntax looks like:

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")
jocassid
  • 4,429
  • 1
  • 13
  • 6
  • OK, but your code still suffers the same deadlock problem as the code by @jabaldonedo. – Martin Prikryl Feb 22 '21 at 19:02
  • What deadlock problem is that? The connection is still open when stdout is read and SSHClient.__exit__ will take care of closing the connection at the end of the with block. – jocassid Feb 25 '21 at 15:32
  • I've linked the problem in my comment to the @jabaldonedo's answer already. If you need it repeated, here it is: [Paramiko ssh die/hang with big output](https://stackoverflow.com/q/31625788/850848). – Martin Prikryl Feb 25 '21 at 16:05
-1
# 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)

Oberst
  • 477
  • 11
  • 19
Harshan Gowda
  • 181
  • 2
  • 10
  • I used your method to get to an interactive menu. I want to type "R" and press Enter, but the remote_conn.send("R\n") doesn't do anything. The shell is not taking the "R". What can I do here? Doing stdin.write("R") returns 'tuple does not have method write' – Alichino Mar 02 '20 at 10:28