J'essaie d'exécuter une commande interactive via paramiko. L'exécution de cmd essaie de demander un mot de passe mais je ne sais pas comment fournir le mot de passe via exec_command de paramiko et l'exécution se bloque. Existe-t-il un moyen d'envoyer des valeurs au terminal si une exécution de cmd attend une entrée de manière interactive?
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")
Est-ce que quelqu'un sait comment cela peut être abordé? Je vous remercie.
La distribution complète de paramiko est livrée avec beaucoup de bons démos .
Dans le sous-répertoire demos, demo.py
et interactive.py
ont des exemples interactifs complets de TTY qui seraient probablement excessifs dans votre cas.
Dans votre exemple ci-dessus, ssh_stdin
se comporte comme un objet de fichier Python standard, donc ssh_stdin.write
devrait fonctionner tant que le canal est toujours ouvert.
Je n'ai jamais eu besoin d'écrire sur stdin, mais la documentation suggère qu'un canal est fermé dès qu'une commande se ferme. Il est donc probable que l'utilisation de la méthode standard stdin.write
pour envoyer un mot de passe ne fonctionnera pas. Il y a des commandes de paramiko de niveau inférieur sur le canal lui-même qui vous donnent plus de contrôle - voyez comment la méthode SSHClient.exec_command
est implémentée pour tous les détails sanglants.
J'ai eu le même problème en essayant de faire une session ssh interactive en utilisant ssh , un fork de Paramiko.
J'ai fouillé et trouvé cet article:
http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/
Pour continuer votre exemple, vous pourriez faire
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()
L'article va plus en profondeur, décrivant un shell entièrement interactif autour de exec_command. J'ai trouvé cela beaucoup plus facile à utiliser que les exemples de la source.
Vous avez besoin de Pexpect pour tirer le meilleur parti des deux mondes (expect et ssh wrappers).
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()
Pourquoi stdout.read () se bloquera-t-il si vous utilisez différemment sans vérifier stdout.channel.recv_ready (): in pendant que stdout.channel.exit_status_ready ():
Dans mon cas, après la commande d’exécution sur le serveur distant, la session attend la saisie de l’utilisateur. Après la saisie de «q», la connexion sera fermée. Mais avant de saisir 'q', le stdout.read () attend EOF, semble que ce methord ne fonctionne pas si le tampon est plus grand.
Je ne suis pas familier avec paramiko, mais cela peut marcher:
ssh_stdin.write('input value')
ssh_stdin.flush()
Pour plus d'informations sur stdin:
http://docs.python.org/library/sys.html?highlight=stdin#sys.stdin
Regardez l'exemple et faites de la même manière
(extrait de 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