在[此主题] [1]上有一个类似的问题。
我想将命令发送到我的子进程,解释响应,然后发送另一个命令。如果必须启动一个新的子进程来实现这一点似乎是一种耻辱,特别是如果subprocess2必须执行许多与subprocess1相同的任务(例如ssh,open mysql)。
我尝试了以下内容:
subprocess1.stdin.write([my commands])
subprocess1.stdin.flush()
subprocess1.stout.read()
但如果没有明确的字节到read()
的参数,程序就会执行该指令,我无法为read()
提供参数,因为我无法猜出有多少字节可用在溪流中。
我正在运行WinXP,Py2.7.1
感谢@regularfry为我提供了我真实意图的最佳解决方案(阅读他的回复中的评论,因为它们与通过SSH隧道实现我的目标有关)。 (他/她的答案已经被投了票。)然而,为了以后找到标题问题答案的观众的利益,我接受了@Mike Penningtion的回答。
答案 0 :(得分:2)
您的选择是:
答案 1 :(得分:1)
@JellicleCat,我正在跟进评论。我相信wexpect是sage ... AFAIK的一部分,它不是单独打包的,但您可以下载wexpect here。
老实说,如果您要开启程序化ssh会话,请使用paramiko。它作为一个独立的安装支持,具有良好的包装,应该在Windows上本地安装。
示例paramiko脚本cd到目录,执行ls
并退出...捕获所有结果......
import sys
sys.stderr = open('/dev/null') # Silence silly warnings from paramiko
import paramiko as pm
sys.stderr = sys.__stderr__
import os
class AllowAllKeys(pm.MissingHostKeyPolicy):
def missing_host_key(self, client, hostname, key):
return
HOST = '127.0.0.1'
USER = ''
PASSWORD = ''
client = pm.SSHClient()
client.load_system_host_keys()
client.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
client.set_missing_host_key_policy(AllowAllKeys())
client.connect(HOST, username=USER, password=PASSWORD)
channel = client.invoke_shell()
stdin = channel.makefile('wb')
stdout = channel.makefile('rb')
stdin.write('''
cd tmp
ls
exit
''')
print stdout.read()
stdout.close()
stdin.close()
client.close()
答案 2 :(得分:1)
这种方法可行(我已经这样做了)但需要一些时间并且它使用特定于Unix的调用。您将不得不放弃子进程模块并基于fork / exec和os.pipe()滚动自己的等效项。
使用fcntl.fcntl函数在使用os.pipe()创建子进程的stdin / stdout文件描述符(读取和写入)后,将其放入非阻塞模式(O_NONBLOCK选项常量)。
使用select.select函数轮询或等待文件描述符的可用性。为了避免死锁,您需要使用select()来确保写入不会被阻塞,就像读取一样。即使如此,您还必须在读取和写入时考虑OSError异常,并在收到EAGAIN错误时重试。 (即使在读/写之前使用select,EAGAIN也可以在非阻塞模式下发生;这是一个常见的内核错误,已经证明难以修复。)
如果你愿意在Twisted框架上实现,他们应该为你解决这个问题;您所要做的就是编写一个Process子类。但我自己还没试过。