2014-01-29 102 views
5

我想使用子進程產生ssh子進程。如何使用子進程模塊與ssh交互

我工作的Python 2.7.6在Windows 7

這裏是我的代碼:

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

輸出:

None 

標準輸出應該包含: sshserver @本地的密碼:

+0

至少在Linux上(和windows窗口),tty的'stdin'與ssh的'stdin'不一樣,要求輸入密碼。堅持下來,爲此獲得代碼(linux tho)。 – Torxed

+1

如果您需要自動化'ssh',您可能需要調查[pexpect](http://pexpect.sourceforge.net/pexpect.html)或類似內容。您可能還想考慮只使用基於密鑰的身份驗證,以便您不需要密碼密碼。 – larsks

+0

我已經在pexpect上工作過,但它在windows上不能正常工作,這就是爲什麼我要使用標準python模塊的原因@larsks – WannaBeGenius

回答

8

以下是處理SSH代碼的示例在證書部分的「是/否」的提示以及詢問密碼時。

#!/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) 

的原因(和糾正我,如果我錯了這裏)你不能夠讀取stdin直線距離是因爲SSH可以運行作爲下一個不同的進程ID子,你需要讀/附至。

由於您使用的是windows,因此pty將無法​​使用。有兩種解決方案可以更好地發揮作用,這就是pexpect以及有人指出基於密鑰的身份驗證。

爲了實現你只需要做到以下幾點基於密鑰的認證: 在您的客戶端,運行:ssh-keygenid_rsa.pub內容(一行)複製到/home/user/.ssh/authorized_keys在服務器上。

你完成了。 如果沒有,請帶着重點。

import pexpect 
child = pexpect.spawn('ssh [email protected]') 
child.expect('Password:') 
child.sendline('SuperSecretPassword') 
+0

pty模塊要求termios只能在Unix平臺上工作 – WannaBeGenius

+0

我在回答中提到的是不是我? :/ – Torxed

+0

是的,你做了,而且我確實提到了我在windows上工作;) – WannaBeGenius