50

I'm trying to run an interactive command through paramiko. The cmd execution tries to prompt for a password but I do not know how to supply the password through paramiko's exec_command and the execution hangs. Is there a way to send values to the terminal if a cmd execution expects input interactively?

ssh = paramiko.SSHClient()
ssh.connect(server, username=username, password=password)
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("psql -U factory -d factory -f /tmp/data.sql")

Does anyone know how this can addressed? Thank you.

shahjapan
14.5k22 gold badges77 silver badges106 bronze badges
asked Dec 17, 2008 at 4:16
1

7 Answers 7

34

The full paramiko distribution ships with a lot of good demos.

In the demos subdirectory, demo.py and interactive.py have full interactive TTY examples which would probably be overkill for your situation.

In your example above ssh_stdin acts like a standard Python file object, so ssh_stdin.write should work so long as the channel is still open.

I've never needed to write to stdin, but the docs suggest that a channel is closed as soon as a command exits, so using the standard stdin.write method to send a password up probably won't work. There are lower level paramiko commands on the channel itself that give you more control - see how the SSHClient.exec_command method is implemented for all the gory details.

answered Dec 17, 2008 at 7:12
Sign up to request clarification or add additional context in comments.

2 Comments

And, for those of you who got here wanting to only see what the output of a command might be, some code might be: (stdin, stdout, stderr) = Client.exec_command('ls -la') print("\nstdout is:\n" + stdout.read() + "\nstderr is:\n" + stderr.read())
Fixed broken link.
13

I had the same problem trying to make an interactive ssh session using ssh, a fork of Paramiko.

I dug around and found this article:

Updated link (last version before the link generated a 404): http://web.archive.org/web/20170912043432/http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/

To continue your example you could do

ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("psql -U factory -d factory -f /tmp/data.sql")
ssh_stdin.write('password\n')
ssh_stdin.flush()
output = ssh_stdout.read()

The article goes more in depth, describing a fully interactive shell around exec_command. I found this a lot easier to use than the examples in the source.

Original link: http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/

jrd1
10.8k4 gold badges37 silver badges53 bronze badges
answered Sep 14, 2012 at 19:58

1 Comment

The link is broken :(
6

You need Pexpect to get the best of both worlds (expect and ssh wrappers).

answered Jun 22, 2010 at 18:51

1 Comment

I would recommend this as well. Here is an example that controls multiple servers at the same time but it could easily be used on just one. github.com/pexpect/pexpect/blob/master/examples/hive.py
6
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(server_IP,22,username, password)
stdin, stdout, stderr = ssh.exec_command('/Users/lteue/Downloads/uecontrol-CXC_173_6456-R32A01/uecontrol.sh -host localhost ')
alldata = ""
while not stdout.channel.exit_status_ready():
 solo_line = "" 
 # Print stdout data when available
 if stdout.channel.recv_ready():
 # Retrieve the first 1024 bytes
 solo_line = stdout.channel.recv(1024) 
 alldata += solo_line
 if(cmp(solo_line,'uec> ') ==0 ): #Change Conditionals to your code here 
 if num_of_input == 0 :
 data_buffer = "" 
 for cmd in commandList :
 #print cmd
 stdin.channel.send(cmd) # send input commmand 1
 num_of_input += 1
 if num_of_input == 1 :
 stdin.channel.send('q \n') # send input commmand 2 , in my code is exit the interactive session, the connect will close.
 num_of_input += 1 
print alldata
ssh.close() 

Why the stdout.read() will hang if use dierectly without checking stdout.channel.recv_ready(): in while stdout.channel.exit_status_ready():

For my case ,after run command on remote server , the session is waiting for user input , after input 'q' ,it will close the connection . But before inputting 'q' , the stdout.read() will waiting for EOF,seems this methord does not works if buffer is larger .

  • I tried stdout.read(1) in while , it works
    I tried stdout.readline() in while , it works also.
    stdin, stdout, stderr = ssh.exec_command('/Users/lteue/Downloads/uecontrol')
    stdout.read() will hang
answered Sep 28, 2016 at 7:39

2 Comments

This should be made a separate question if you need an answer (as this is an old question). Or atleast it should be a comment on the question or one of the answers. It cannot be an answer by itself.
Excellent answer which helped me forward. For who it might interest: I had problem reading the last line I needed from the command in a multi-threaded application. Stuff just seemed to hang. But then I started issuing ssh_stdout.channel.close() and then doing final read with ssh_stdout.channel.recv(1000) . Boom, no more hangs! (Of course everyone should consider if this method is applicable to their code.)
3

I'm not familiar with paramiko, but this may work:

ssh_stdin.write('input value')
ssh_stdin.flush()

For information on stdin:

http://docs.python.org/library/sys.html?highlight=stdin#sys.stdin

answered Dec 17, 2008 at 5:44

1 Comment

NOTE: Always make sure to flush() any buffer you're writing to the way this example correctly shows; forgetting (or not knowing) to do this is a common cause for frustration.
0

Take a look at example and do in similar way

(sorce from http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/):

 ssh.connect('127.0.0.1', username='jesse', 
 password='lol')
 stdin, stdout, stderr = ssh.exec_command(
 "sudo dmesg")
 stdin.write('lol\n')
 stdin.flush()
 data = stdout.read.splitlines()
 for line in data:
 if line.split(':')[0] == 'AirPort':
 print line
answered May 30, 2016 at 8:28

1 Comment

Source link broken
-1

You can use this method to send whatever confirmation message you want like "OK" or the password. This is my solution with an example:

def SpecialConfirmation(command, message, reply):
 net_connect.config_mode() # To enter config mode
 net_connect.remote_conn.sendall(str(command)+'\n' )
 time.sleep(3)
 output = net_connect.remote_conn.recv(65535).decode('utf-8')
 ReplyAppend=''
 if str(message) in output:
 for i in range(0,(len(reply))):
 ReplyAppend+=str(reply[i])+'\n'
 net_connect.remote_conn.sendall(ReplyAppend)
 output = net_connect.remote_conn.recv(65535).decode('utf-8') 
 print (output)
 return output
CryptoPkiEnroll=['','','no','no','yes']
output=SpecialConfirmation ('crypto pki enroll TCA','Password' , CryptoPkiEnroll )
print (output)
creyD
2,1264 gold badges34 silver badges67 bronze badges
answered Jun 24, 2019 at 22:13

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.