Executar comandos interativos em paramiko
Pergunta
Eu estou tentando executar um comando interativo através paramiko. As tentativas de execução de cmd para solicitar uma senha, mas eu não sei como fornecer a senha através exec_command de paramiko e os trava de execução. Existe uma maneira de enviar valores para o terminal se uma execução cmd espera de entrada interativa?
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")
Alguém sabe como isso pode abordadas? Obrigado.
Solução
Os paramiko navios distribuição completa com um monte de bom demos .
No subdiretório demos, demo.py
e interactive.py
temos exemplos TTY interativos completos que provavelmente seria um exagero para a sua situação.
No seu exemplo acima ssh_stdin
age como um objeto de arquivo padrão do Python, então ssh_stdin.write
deve funcionar, desde que o canal ainda está aberto.
Eu nunca precisei escrever para stdin, mas os docs sugerem que um canal é fechada assim como um comando saídas, portanto, usando o método stdin.write
padrão para enviar uma senha-se, provavelmente, não vai funcionar. Existem comandos nível paramiko mais baixos no próprio canal que lhe dão mais controle - ver como o SSHClient.exec_command
método é implementado para todos os detalhes.
Outras dicas
Eu tive o mesmo problema ao tentar fazer uma sessão SSH interativo usando ssh , um garfo de paramiko.
Eu cavei ao redor e encontrei este artigo:
link Atualizado (última versão antes do link gerado a 404): http://web.archive.org/web/20170912043432/http://jessenoller.com/2009/ 05/02 / ssh-programming-com-paramiko-completamente-diferente /
Para continuar o seu exemplo, você poderia fazer
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()
O artigo vai mais em profundidade, descrevendo um shell totalmente interativo em torno exec_command. Achei isso muito mais fácil de usar do que os exemplos a fonte.
link Original : http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/
Você precisa Pexpect para obter o melhor dos dois mundos (esperar e invólucros ssh).
Eu não estou familiarizado com paramiko, mas isso pode funcionar:
ssh_stdin.write('input value')
ssh_stdin.flush()
Para obter informações sobre stdin:
http://docs.python.org/library /sys.html?highlight=stdin#sys.stdin
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()
Por que a stdout.read () irá travar se o uso dierectly sem verificar stdout.channel.recv_ready (): em enquanto stdout.channel.exit_status_ready ():
Para o meu caso, depois de comando executado no servidor remoto, a sessão está aguardando entrada do usuário, após a entrada de 'q', que vai fechar a conexão. Mas antes de introduzir 'q', o stdout.read () irá esperar por EOF, parece que este methord não funciona se tampão é maior.
- Eu tentei stdout.read (1) no tempo, ele funciona
Tentei stdout.readline () no tempo, ele funciona também.
stdin, stdout, stderr = ssh.exec_command ( '/ Users / lteue / downloads / uecontrol')
stdout.read () irá travar
Dê uma olhada exemplo e fazer em forma similar
(sorce de http: // jessenoller. cOM / 2009/02/05 / ssh-programming-with-paramiko-completamente-diferente / ):
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
Você pode usar esse método para enviar qualquer mensagem de confirmação que você quer como "OK" ou a senha. Esta é a minha solução com um exemplo:
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)