2014-04-04 16 views
8

Tôi đang sử dụng phương thức popen3 của để bắt đầu quá trình hoạt động theo kiểu/REPL kiểu bàn điều khiển để liên tục chấp nhận đầu vào và đầu ra trả về.ruby ​​popen3 - làm thế nào để liên tục viết để stdin & đọc stdout mà không cần mở lại quá trình?

tôi có thể mở quá trình này, gửi đầu vào, và nhận được kết quả tốt, với mã như thế này:

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 

tôi muốn làm điều đó nhiều lần trong một hàng, mà không cần mở quá trình, vì phải mất một thời gian dài để bắt đầu.

Tôi biết tôi phải đóng stdin để stdout trở lại .. nhưng những gì tôi không biết là, làm cách nào để 'mở lại' stdin để tôi có thể viết thêm đầu vào?

Lý tưởng nhất là tôi muốn làm một cái gì đó như thế này:

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 

giải pháp

Nhờ câu trả lời pmoo, tôi đã có thể đưa ra một giải pháp sử dụng PTYexpect, mong các chuỗi dấu nhắc rằng quá trình này trả về bất cứ khi nào nó sẵn sàng cho nhiều đầu vào hơn, như vậy:

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 

Trả lời

3

Bạn có thể có một số thành công khi sử dụng expect thư viện, và có quá trình con để đánh dấu một cách rõ ràng vào cuối mỗi đầu ra, như:

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 

Như một phần thưởng, expect có một lựa chọn timeout.

Các vấn đề liên quan