2014-01-29 3 views
5

Ich versuche, einen ssh Kindprozess mit Subprozess zu spawnen.Wie mit ssh mit Subprozessmodul interagieren

Ich arbeite an Python 2.7.6 auf Windows 7

hier ist mein Code:

from subprocess import * 
r=Popen("ssh [email protected]", stdout=PIPE) 
stdout, stderr=r.communicate() 
print(stdout) 
print(stderr) 

Die Ausgänge:

None 

stdout enthalten: sshserver @ localhost des passwort:

+0

Unter Linux zumindest (und Prob Windows) ist die 'stdin' Ihres tty nicht das selbe wie das ssh fragt nach dem Passwort. Warte, Code dafür (linux tho). – Torxed

+1

Wenn Sie 'ssh' automatisieren müssen, möchten Sie wahrscheinlich etwas wie [pexpect] (http://pexpect.sourceforge.net/pexpect.html) oder ähnliches untersuchen. Sie sollten auch nur die schlüsselbasierte Authentifizierung in Erwägung ziehen, damit Sie sich nicht mit Passwörtern herumärgern müssen. – larsks

+0

Ich habe bereits an pexpect gearbeitet, aber es funktioniert nicht perfekt unter Windows, deshalb möchte ich Standard-Python-Module verwenden @larsks – WannaBeGenius

Antwort

8

Hier ist ein Beispiel für funktionierenden SSH-Code, der handl Es ist der Prompt für Ja/Nein auf dem Zertifikatsteil und auch wenn nach einem Passwort gefragt wird.

#!/usr/bin/python 

import pty, sys 
from subprocess import Popen, PIPE, STDOUT 
from time import sleep 
from os import fork, waitpid, execv, read, write 

class ssh(): 
    def __init__(self, host, execute='echo "done" > /root/testing.txt', askpass=False, user='root', password=b'SuperSecurePassword'): 
     self.exec = execute 
     self.host = host 
     self.user = user 
     self.password = password 
     self.askpass = askpass 
     self.run() 

    def run(self): 
     command = [ 
       '/usr/bin/ssh', 
       self.user+'@'+self.host, 
       '-o', 'NumberOfPasswordPrompts=1', 
       self.exec, 
     ] 

     # PID = 0 for child, and the PID of the child for the parent  
     pid, child_fd = pty.fork() 

     if not pid: # Child process 
      # Replace child process with our SSH process 
      execv(command[0], command) 

     ## if we havn't setup pub-key authentication 
     ## we can loop for a password promt and "insert" the password. 
     while self.askpass: 
      try: 
       output = read(child_fd, 1024).strip() 
      except: 
       break 
      lower = output.lower() 
      # Write the password 
      if b'password:' in lower: 
       write(child_fd, self.password + b'\n') 
       break 
      elif b'are you sure you want to continue connecting' in lower: 
       # Adding key to known_hosts 
       write(child_fd, b'yes\n') 
      elif b'company privacy warning' in lower: 
       pass # This is an understood message 
      else: 
       print('Error:',output) 

     waitpid(pid, 0) 

Der Grund (und mich korrigieren, wenn ich hier falsch liege) für Sie nicht die stdin gerade weg, weil SSH als Unterprozess unter einem anderen Prozess-ID, die Sie/lesen müssen läuft lesen zu können anhängen zu.

Da Sie Windows verwenden, wird pty nicht funktionieren. Es gibt zwei Lösungen, die besser funktionieren würden und das ist pexpect und jemand wies auf die schlüsselbasierte Authentifizierung hin.

Um eine schlüsselbasierte Authentifizierung Sie nur Folgendes tun müssen zu erreichen: Auf dem Client ausgeführt wird: ssh-keygen Kopieren Sie Ihre id_rsa.pub Inhalt (eine Zeile) in /home/user/.ssh/authorized_keys auf dem Server.

Und du bist fertig. Wenn nicht, gehen Sie mit pexpect.

+0

das Pty-Modul erfordert Terminals, die nur auf Unix-Plattform funktioniert – WannaBeGenius

+0

Welche ich in meiner Antwort erwähnt habe ich nicht? :/ – Torxed

+0

ja du hast, und ich habe erwähnt, dass ich an Windows arbeite;) – WannaBeGenius