2014-04-04 51 views
8

我正在使用Open3popen3方法来启动一个以控制台/ REPL方式运行的进程,以重复接受输入和返回输出。ruby​​ popen3 - 如何重复写入标准输入和读取标准输出而不重新打开过程?

我能够打开的过程中,输入发送和接收输出就好了,有这样的代码:

Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr| 
    stdin.puts "a string of input" 
    stdin.close_write 
    stdout.each_line { |line| puts line } #successfully prints all the output 
end 

我想做的事情,很多时候一排,而无需重新打开过程,因为启动需要很长时间。

我知道我必须关闭标准输入才能使stdout返回..但我不知道的是,如何重新打开stdin以便我可以写入更多输入?

理想我想要做这样的事情:

Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr| 
    stdin.puts "a string of input" 
    stdin.close_write 
    stdout.each_line { |line| puts line } 

    stdin.reopen_somehow() 

    stdin.puts "another string of input" 
    stdin.close_write 
    stdout.each_line { |line| puts line } 
    # etc.. 
end 

解决方案

由于pmoo的回答,我能够用PTYexpect制定一个解决方案,期待提示字符串的进程每当它准备好更多输入时就会返回,如下所示:

PTY.spawn("console_REPL_process") do |output, input| 
    output.expect("prompt >") do |result| 
     input.puts "string of input" 
    end 
    output.expect("prompt >") do |result| 
     puts result 
     input.puts "another string of input" 
    end 
    output.expect("prompt >") do |result| 
     puts result 
     input.puts "a third string of input" 
    end 
    # and so forth 
end 

回答

3

您可以使用expect库,并有子进程来明确地标记每个输出端,如:

require 'expect' 
require 'open3' 

Open3.popen3("/bin/bash") do 
    | input, output, error, wait_thr | 
    input.sync = true 
    output.sync = true 

    input.puts "ls /tmp" 
    input.puts "echo '----'" 
    puts output.expect("----", 5) 

    input.puts "cal apr 2014" 
    input.puts "echo '----'" 
    puts output.expect("----", 5) 
end 

作为奖励,expecttimeout选项。

相关问题