使用Jython Subprocess将命令发送到bash shell

时间:2016-11-04 14:07:13

标签: python bash shell


我需要在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

1 个答案:

答案 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 ..")