Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用子流程模块与ssh交互_Python_Subprocess_Popen - Fatal编程技术网

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

Python 如何使用子流程模块与ssh交互,python,subprocess,popen,Python,Subprocess,Popen,我正在尝试使用subprocess生成一个ssh子进程 我正在Windows7上开发Python2.7.6 这是我的密码: from subprocess import * r=Popen("ssh sshserver@localhost", stdout=PIPE) stdout, stderr=r.communicate() print(stdout) print(stderr) 产出: None 标准输出应包含: sshserver@localhost的密码:下面是一个工作SSH代码的

我正在尝试使用subprocess生成一个ssh子进程

我正在Windows7上开发Python2.7.6

这是我的密码:

from subprocess import *
r=Popen("ssh sshserver@localhost", stdout=PIPE)
stdout, stderr=r.communicate()
print(stdout)
print(stderr)
产出:

None
标准输出应包含:
sshserver@localhost的密码:

下面是一个工作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,您需要读取/附加到该进程ID

由于您使用的是windows,
pty
将无法工作。有两种解决方案工作得更好,正如有人指出的那样,基于密钥的身份验证

为了实现基于密钥的身份验证,您只需执行以下操作: 在客户端上,运行:
ssh-keygen
将您的
id\u rsa.pub
内容(一行)复制到服务器上的
/home/user/.ssh/authorized\u keys

你完成了。 如果没有,请选择pexpect

import pexpect
child = pexpect.spawn('ssh user@host.com')
child.expect('Password:')
child.sendline('SuperSecretPassword')

至少在Linux(和prob windows)上,tty的
stdin
与ssh请求的密码不同。等一下,有了这方面的代码(LinuxTho)。如果您需要自动化
ssh
,您可能需要研究类似的东西。您可能还想考虑只使用基于密钥的身份验证,这样您就不需要用密码来处理了。我已经在pWEY上工作了,但是它在Windows上不太完美,这就是为什么我想使用标准Python模块@larsks@user3249194您不能为此使用标准模块。Windows不允许您连接到子进程ID。我读到有人摆弄win32库,试图更改主循环的进程权限,以便附加到子进程ID并读取标准输出。但简而言之,这是不可能的。我已经在下面公布了你的3个已知有效的选项。第一个是Linux解决方案,所以你可能对此不感兴趣,除非你想掌握生活并使用合适的操作系统,呵呵:)@Torxed我已经安装了debian并与pexpect合作,但是我想为windows找到一个解决方案:DTPTY模块需要termios,它只在Unix平台上工作,我在回答中提到过,不是吗/是的,你说了,我也说过我在windows上工作;)这就是为什么我发布了另外两个在Windows中工作的解决方案;)注意:Linux修复程序适用于阅读本文的任何其他人(因为这是一个常见问题,会有很多其他人来到这里),而且您现在有一台Linux机器,因此这也会对您有所帮助:您的答案中的解决方案在Windows上不起作用
pexpect
needs
pty
需要一个POSIX系统(
pty
是为Linux编写的)。