我正在尝试使用子进程spawn一个ssh子进程。
我在Windows 7上使用Python 2.7.6进行开发。
这是我的代码:
from subprocess import *
r=Popen("ssh sshserver@localhost", stdout=PIPE)
stdout, stderr=r.communicate()
print(stdout)
print(stderr)
输出结果:
None
标准输出应包含: sshserver@localhost的密码:
我正在尝试使用子进程spawn一个ssh子进程。
我在Windows 7上使用Python 2.7.6进行开发。
这是我的代码:
from subprocess import *
r=Popen("ssh sshserver@localhost", stdout=PIPE)
stdout, stderr=r.communicate()
print(stdout)
print(stderr)
None
标准输出应包含: sshserver@localhost的密码:
#!/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-keygen
将id_rsa.pub
内容(一行)复制到服务器上的/home/user/.ssh/authorized_keys
中。
然后你就完成了。 如果没有,就使用pexpect。
import pexpect
child = pexpect.spawn('ssh user@host.com')
child.expect('Password:')
child.sendline('SuperSecretPassword')
pexpect
需要 pty
,而 pty
是针对Linux编写的,需要期望一个POSIX系统。 - jfs
ssh
,你可能想要调查类似pexpect的工具。你也可以考虑使用基于密钥的身份验证,这样就不需要处理密码了。 - larsksPopen()
来让它正常工作,但是你不能使用第三方SSH客户端。 - Torxed