Выполнение интерактивных команд в 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-обертки).
Ответ 4
Я не знаком с paramiko, но это может сработать:
ssh_stdin.write('input value')
ssh_stdin.flush()
Информация о stdin:
http://docs.python.org/library/sys.html?highlight=stdin#sys.stdin
Ответ 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)