Выполнение интерактивных команд в Paramiko

Я пытаюсь запустить интерактивную команду через paramiko. Выполнение cmd пытается запросить пароль, но я не знаю, как предоставить пароль через paramiko exec_command и выполнение зависает. Есть ли способ отправить значения терминалу, если выполнение cmd ожидает ввода в интерактивном режиме?

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")

Кто-нибудь знает, как это можно решить? Спасибо.

Ответ 1

Полное распределение paramiko поставляется с большим количеством хороших demos.

В подкаталоге demos demo.py и interactive.py есть полные интерактивные примеры TTY, которые, вероятно, будут излишними для вашей ситуации.

В вашем примере выше ssh_stdin действует как стандартный файловый объект Python, поэтому ssh_stdin.write должен работать, пока канал все еще открыт.

Мне никогда не приходилось писать в stdin, но документы предлагают, чтобы канал был закрыт, как только выйдет команда, поэтому использование стандартного метода stdin.write для отправки пароля, вероятно, не будет работать. На самом канале есть команды нижнего уровня paramiko, которые дают вам больше контроля - посмотрите, как метод SSHClient.exec_command реализован для всех деталей gory.

Ответ 2

У меня возникла та же проблема, когда я пытался сделать интерактивную сессию ssh, используя ssh, форк Paramiko.

Я покопался и нашел эту статью:

Обновленная ссылка (последняя версия перед тем, как ссылка создала 404): http://web.archive.org/web/20170912043432/http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely -разные/

Чтобы продолжить ваш пример, вы можете сделать

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()

Статья более подробно описывает полностью интерактивную оболочку вокруг exec_command. Я нашел это намного проще в использовании, чем примеры в источнике.

Оригинальная ссылка: http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/

Ответ 3

Вам нужен Pexpect, чтобы получить лучшее из обоих миров (ожидается и ssh-обертки).

Ответ 5

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()              

Почему stdout.read() будет зависать, если использовать dierectly, не проверяя stdout.channel.recv_ready(): in, в то время как stdout.channel.exit_status_ready():

В моем случае после запуска команды на удаленном сервере сеанс ожидает ввода пользователем, после ввода "q" он закроет соединение. Но перед вводом "q" stdout.read() будет ждать EOF, кажется, что этот метод не работает, если буфер больше.

  • Я пытался использовать stdout.read(1), пока он работает  Я попробовал stdout.readline(), пока он работает.
     stdin, stdout, stderr = ssh.exec_command ('/Пользователи/lteue/Downloads/uecontrol')
     stdout.read() будет висеть

Ответ 6

Взгляните на пример и сделайте аналогичным образом

(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

Ответ 7

Вы можете использовать этот метод для отправки любого подтверждающего сообщения, например "ОК" или пароля. Это мое решение с примером:

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)