最后,我能够使用 pty 模块通过伪终端控制 ssh。我在 中编写了一个解决方案pexpect
,然后通过查看 pexpect 源代码并从这个 StackOverflow 答案中获得一些帮助,我能够弄清楚该怎么做。这是相关代码的摘录(作为对象方法的一部分执行;因此引用self
)。
command = [
'/usr/bin/ssh',
'{0}@{1}'.format(username, hostname),
'-L', '{0}:localhost:{1}'.format(local_port, foreign_port),
'-o', 'NumberOfPasswordPrompts=1',
'sleep {0}'.format(SLEEP_TIME),
]
# PID = 0 for child, and the PID of the child for the parent
self.pid, child_fd = pty.fork()
if not self.pid: # Child process
# Replace child process with our SSH process
os.execv(command[0], command)
while True:
output = os.read(child_fd, 1024).strip()
lower = output.lower()
# Write the password
if lower.endswith('password:'):
os.write(child_fd, self.password_var.get() + '\n')
break
elif 'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
os.write(child_fd, 'yes\n')
elif 'company privacy warning' in lower:
pass # This is an understood message
else:
tkMessageBox.showerror("SSH Connection Failed",
"Encountered unrecognized message when spawning "
"the SSH tunnel: '{0}'".format(output))
self.disconnect()