ruby popen3 -- 如何重复写入标准输入 &无需重新打开过程即可读取标准输出? [英] ruby popen3 -- how to repeatedly write to stdin & read stdout without re-opening process?

查看:54
本文介绍了ruby popen3 -- 如何重复写入标准输入 &无需重新打开过程即可读取标准输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Open3popen3 方法启动一个在类似控制台的过程中运行/REPL 重复接受输入并返回输出的方式.

我可以用这样的代码打开进程、发送输入和接收输出:

Open3.popen3("console_REPL_process") 做 |stdin、stdout、stderr、wait_thr|stdin.puts "一串输入"标准输入.close_writestdout.each_line { |行|puts line } #成功打印所有输出结尾

我想连续多次执行此操作,而无需重新打开该过程,因为启动需要很长时间.

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

理想情况下,我想做这样的事情:

Open3.popen3("console_REPL_process") 做 |stdin、stdout、stderr、wait_thr|stdin.puts "一串输入"标准输入.close_writestdout.each_line { |行|放置线 }stdin.reopen_somehow()stdin.puts "另一串输入"标准输入.close_writestdout.each_line { |行|放置线 }# 等等..结尾

解决方案

感谢 pmoo 的回答,我能够使用 PTYexpect 设计一个解决方案,期待进程在准备好更多输入时返回的提示字符串,像这样:

PTY.spawn("console_REPL_process") 做|输出,输入|output.expect("prompt >") do |result|input.puts 输入字符串"结尾output.expect("prompt >") do |result|结果input.puts "另一串输入"结尾output.expect("prompt >") do |result|结果input.puts "第三个输入字符串"结尾#等等结尾

解决方案

您可以使用 expect 库取得一些成功,并让子进程明确标记每个输出的结束,例如:

需要'期望'需要'open3'Open3.popen3("/bin/bash") 做|输入、输出、错误、wait_thr |input.sync = 真output.sync = 真input.puts "ls/tmp"input.puts "echo '----'"puts output.expect("----", 5)input.puts "cal apr 2014"input.puts "echo '----'"puts output.expect("----", 5)结尾

作为奖励,expect 有一个 timeout 选项.

I am using Open3's popen3 method to start a process that functions in a console-like / REPL fashion to repeatedly accept input and return output.

I am able to open the process, send input, and receive the output just fine, with code like this:

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

I want to do that many times in a row, without re-opening the process, as it takes a long time to start up.

I know I have to close stdin in order for stdout to return.. but what I don't know is, how do I 'reopen' stdin so I can write more input?

Ideally I want to do something like this:

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

solution

Thanks to pmoo's answer, I was able to devise a solution using PTY and expect, expecting the prompt string that the process returns whenever it is ready for more input, like so:

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

解决方案

You can have some success using expect library, and have the child process to explicitly mark the end of each output, like:

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

As a bonus, expect has a timeout option.

这篇关于ruby popen3 -- 如何重复写入标准输入 &无需重新打开过程即可读取标准输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆