如何使用子进程模块与ssh交互

Wan*_*ius 5 python subprocess popen

我正在尝试使用子进程生成一个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)
Run Code Online (Sandbox Code Playgroud)

产出:

None
Run Code Online (Sandbox Code Playgroud)

stdout应该包含:sshserver @ localhost的密码:

Tor*_*xed 8

下面是一个使用SSH代码的示例,它可以在证书部分处理yes/no的promt,也可以在要求输入密码时使用.

#!/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)
Run Code Online (Sandbox Code Playgroud)

你无法立即阅读的原因(并纠正我,如果我错在这里)stdin是因为SSH在您需要读取/附加到的不同进程ID下作为子进程运行.

由于您使用的是Windows,pty因此无法使用.有两种解决方案,将更好地工作,这就是Pexpect的,并有人指出,基于密钥的认证.

要实现基于密钥的身份验证,您只需执行以下操作:在客户端上,运行:ssh-keygenid_rsa.pub内容(一行)复制到/home/user/.ssh/authorized_keys服务器上.

而且你已经完成了.如果没有,请选择pexpect.

import pexpect
child = pexpect.spawn('ssh user@host.com')
child.expect('Password:')
child.sendline('SuperSecretPassword')
Run Code Online (Sandbox Code Playgroud)

  • 您的答案中的解决方案不适用于Windows.`pexpect`需要`pty`,它需要一个POSIX系统(`pty`是为Linux编写的). (2认同)