如何在Python中从子进程向SSH传递命令

如何在Python中从子进程向SSH传递命令,python,bash,ssh,subprocess,Python,Bash,Ssh,Subprocess,我使用了Python 2.7.6中的子流程模块来建立SSH。我意识到不建议这样做,但我无法安装其他Python SSH库,如paramiko和fabric 我只是想知道是否有人不介意告诉我现在的情况 sshProcess = subprocess.call(['ssh', '-t', '<REMOTE>', 'ssh', '<REMOTE>']) sshProcess=subprocess.call(['ssh','-t',''ssh','') 我想使用子流程方法在

我使用了Python 2.7.6中的
子流程
模块来建立SSH。我意识到不建议这样做,但我无法安装其他Python SSH库,如paramiko和fabric

我只是想知道是否有人不介意告诉我现在的情况

sshProcess = subprocess.call(['ssh', '-t', '<REMOTE>', 'ssh', '<REMOTE>']) 
sshProcess=subprocess.call(['ssh','-t',''ssh','')
我想使用子流程方法在
REMOTE
中执行命令。有没有办法做到这一点?不幸的是,
REMOTE
受用户手动输入的密码保护。如果有帮助的话,我正在运行Windows10BashShell


感谢您的帮助

运行远程命令就像将其放在命令行上一样简单。(这对于SSH服务器在协议级别上与在stdin上提供它是有区别的,但是所讨论的协议是为编程使用而构建的,而不是为人使用而构建的——因为后者是交互式shell模型背后的设计意图)

顺便说一句,如果您想在只进行一次身份验证后通过不同的SSH调用在单个连接上运行多个命令,我强烈建议您使用Paramiko,但您可以使用OpenSSH命令行工具来实现


假设您有一个表示远程命令的数组:

myCommand = [ 'ls', '-l', '/tmp/my directory name with spaces' ]
要将其转换为字符串(以尊重空格的方式,并且不能让恶意选择的名称在远程服务器上运行任意命令),您可以使用:

myCommandStr = ' '.join(pipes.quote(n) for n in myCommand)
现在,您可以将一些内容作为命令行参数传递给ssh:

subprocess.call(['ssh', '-t', hostname, myCommandStr])
但是,假设您想要嵌套这个。您可以重复此过程:

myCommand = [ 'ssh', '-t', hostname1, myCommandStr ]
myCommandStr = ' '.join(pipes.quote(n) for n in myCommand)
subprocess.call(['ssh', '-t', hostname2, myCommandStr])
因为我们没有重定向stdin或stdout,它们仍然应该指向启动Python程序的终端,所以SSH应该能够直接执行其密码提示


这就是说,特别是对于通过临时系统执行ssh,您不需要经历这么多麻烦:您可以告诉
ssh
使用
ProxyJump
选项为您完成这项工作:

myCommand = [ 'ls', '-l', '/tmp/my directory name with spaces' ]
myCommandStr = ' '.join(pipes.quote(n) for n in myCommand)
subprocess.call(['ssh', '-o', 'ProxyJump=%s' % hostname1, hostname2, myCommandStr])

从你的评论中,你说你可以连接。因此,在这之后,要使用子流程通过ssh进行交互,您将需要以下内容:

ssh = subprocess.Popen(['ssh', <remote client>],
                           stdin=subprocess.PIPE, 
                           stdout = subprocess.PIPE)
back  = ssh.stdout.readlines()
if result == []:
    error = ssh.stderr.readlines()
    print error
else:
    print back
ssh.stdin.write("ls\n")

至少,您应该区分
。您如何构建
命令
也很重要——如果您是在替换变量而不是运行常量命令,那么就存在安全问题……您的标题说您的问题是“如何传递命令”,但目前唯一明显的是您不知道如何传递密码。您试图做的是:重新生成要运行的远程命令,以及该命令如何失败,这一点很重要。这也很重要,因为您的Python程序是否从用户所在的TTY运行,并且能够以交互方式输入密码。@charlesduff感谢您的响应。是,用户正在以交互方式输入密码。我刚意识到我的问题措辞不当。基本上,我可以很好地建立联系。但是现在我尝试在用户输入身份验证详细信息后自动将命令传递到ssh中。一个选项是为用户设置无密码登录,这样就不需要密码。这是通过在客户端生成密钥,然后在服务器上更新密钥来实现的。对于unixy系统,这是通过
ssh-keygen
ssh-copy-id
完成的,但您必须弄清楚
ssh
客户端是如何完成的。
ssh.stdout.readlines()
将永远挂起,除非stdout关闭(此后您将无法阅读更多内容),走这条路线意味着SSH进程在TTY上不再有句柄(因为您使用管道覆盖它),因此它不能直接提示输入密码。