51

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.

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.

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/

1 Comment

The link is broken :(
6

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

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

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

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

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)

Comments

Your Answer

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.