我需要在Jython引擎中向一个 bash shell发送一些后续命令。
使用os.system(s)或subsystem.call(s,...)逐个执行命令不起作用,因为每次都会创建一个新的shell。
我希望有人有一个想法....以下3次测试不是一个充分的洗脱。
Sample Commands : <br>
cd /home/xxx/dir1/dir2<br>
pwd<br>
cd ..<br>
pwd
在第一个测试中,执行命令,但仅在结束时检索输出。
def testRun1():
# Actual Output
# run 0
# run 1
# run 2
# /home/usr/dir1/dir2
# /home/usr/dir1
# /home/usr
print 'All output is shown at the end...'
proc = subprocess.Popen('/bin/bash',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
for i in range(3):
print 'run ' + str(i)
proc.stdin.write('pwd\n')
proc.stdin.write('cd ..\n')
output = proc.communicate()[0]
print output
而'期望的输出'是
# run 0
# /home/usr/dir1/dir2
# run 1
# /home/usr/dir1
# run 2
# /home/usr
第二次试用提供了我们想要的东西,但输出仅在jython脚本被中断时显示。
def testRun2():
# Weird : it is what we want, but all output is blocked until CTRL-C is pressed
# run 0
# /home/usr/dir1/dir2
# run 1
# /home/usr/dir1
# run 2
# /home/usr
proc = subprocess.Popen('/bin/bash',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
for i in range(3):
print 'run ' + str(i)
proc.stdin.write('pwd\n')
proc.stdin.write('cd ..\n')
print 'start to print output'
for line in proc.stdout:
print(line.decode("utf-8"))
print_remaining(proc.stdout)
print 'printed output'
最后一次试用在第二次运行中崩溃,因为流已关闭。
def testRun3():
# This fails with error
# ValueError: I/O operation on closed file
proc = subprocess.Popen('/bin/bash',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
for i in range(3):
print 'run ' + str(i)
proc.stdin.write('pwd\n')
proc.stdin.write('cd ..\n')
output = proc.communicate()[0]
print output
答案 0 :(得分:0)
您遇到的麻烦只与subprocess
部分有关。管道从根本上说是这项工作的错误IPC机制。要将交互式命令解释器置于脚本控制之下,您想要的是pseudoterminal,即使这样,它也不像读写那么简单。
Python标准库没有任何内置模块可以为您进行伪终端处理,除非他们最近添加了一些我不知道的内容。但是,第三方软件包pexpect可以执行此操作,并且它完全针对您要执行的操作。
使用基本的pexpect API:
import pexpect
def testRun4():
proc = pexpect.spawn("/bin/bash")
for i in range(3):
proc.expect(":^[^$#]*[$#] *")
print("run", i)
proc.sendline("pwd")
proc.expect("^[^$#]*[$#] *")
print(proc.before)
proc.sendline("cd ..")
使用pexpect.replwrap
,设置起来要多一些,但循环更整洁:
def testRun5():
proc = pexpect.replwrap.REPLWrapper(
"/bin/bash",
orig_prompt="^[^$#]*[$#] *",
prompt_change="PS1='{}'; PS2='{}'")
for i in range(3):
print("run", i)
print(proc.run_command("pwd"))
proc.run_command("cd ..")