[英]Use Jython Subprocess to send commands to bash shell
I need to send a number of subsequent commands to one bash shell in a Jython engine. 我需要向Jython引擎的一个 bash shell发送许多后续命令。 Executing commands 1 by 1, with os.system(s) or subsystem.call(s, ...) does not work as a new shell is created every time.
用os.system(s)或subsystem.call(s,...)执行命令1到1,因为每次都创建一个新的shell,所以该命令不起作用。
I hope someone has an idea .... following 3 tests are not a sufficient slution. 我希望有人有一个主意..以下3个测试尚不足够。
Sample Commands : <br>
cd /home/xxx/dir1/dir2<br>
pwd<br>
cd ..<br>
pwd
In this first test, the commands are executed, but the output is only retrieved at the end. 在第一个测试中,将执行命令,但仅在最后检索输出。
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
Whereas the 'desired output' is 而“期望的输出”是
# run 0
# /home/usr/dir1/dir2
# run 1
# /home/usr/dir1
# run 2
# /home/usr
This second tryout delivers what we want, but the output is only shown when jython script is interrupted. 第二个尝试提供了我们想要的,但是只有在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'
This last tryout crashes in the second run because a stream was closed. 由于关闭了流,因此最后一次试运行在第二次运行中崩溃。
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
The troubles you're having are only partially to do with subprocess
. 您遇到的麻烦仅与
subprocess
。 Pipes are fundamentally the wrong IPC mechanism for this job. 管道从根本上来说是错误的IPC机制。 To put an interactive command interpreter under scripted control, what you want is a pseudoterminal , and even then it's not as simple as reading and writing.
要将交互式命令解释器置于脚本控制下,您需要的是一个伪终端 ,即使如此,它也不像读写那样简单。
The Python standard library doesn't have any built-in modules that do pseudoterminal handling for you, unless they've added something very recently that I'm not aware of. Python标准库没有任何内置模块可以为您进行伪终端处理,除非它们最近添加了我不知道的内容。 However, the third-party package pexpect can do it, and it's geared for exactly the thing you are trying to do.
但是,第三方程序包pexpect可以做到,它完全适合您要尝试做的事情。
Using the basic pexpect API: 使用基本的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 ..")
With pexpect.replwrap
, it's a little more involved to set up but then the loop is tidier: 使用
pexpect.replwrap
,它的设置要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 ..")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.