如何使用 Ruby 和 IO.popen 写入和读取进程?

问题描述 投票:0回答:2

我写了这个,但没有用...

output = IO.popen("irb", "r+") do |pipe|
  管道获取
  管道.puts“10**6”
  管道获取
  pipeline.puts“退出”
结尾

我这样重写

IO.popen("irb", "w+") 做 |pipe|
  3.times {puts pipeline.gets} # 启动噪音
  管道.puts“10**6
”
  puts pipeline.gets # 我期望“ => 1000000”
  pipeline.puts "quit" # 我希望从 irb 退出
结尾
但它也不起作用

ruby popen
2个回答
5
投票

一般来说,上面的示例将挂起,因为管道仍然打开用于写入,并且您调用的命令(Ruby 解释器)需要更多命令/数据。

另一个答案将

__END__
发送到 ruby——这在这里有效,但是这个技巧当然不适用于您可能通过
popen
调用的任何其他程序。

使用

popen
时,需要用
IO#close_write
关闭管道。

 IO.popen("ruby", "r+") do |pipe|
   pipe.puts "puts 10**6"

   pipe.close_write    # make sure to close stdin for the program you call

   pipe.gets
 end

参见:https://ruby-doc.org/stdlib-3.1.1/libdoc/open3/rdoc/Open3.html

更详细:

在 Ruby 中,

IO.popen
IO.popen2
IO.popen2e
IO.popen3
是用于处理子进程的方法,它们的不同之处在于处理输入、输出和错误流的方式。以下是对差异以及何时使用它们的解释:

  1. IO.popen

    • IO.popen
      是一种多功能方法,允许您创建子流程并与其标准输入和输出交互。
    • 它返回一个数组,其中包含子进程的标准输入、标准输出和代表子进程的线程。
    • 当您需要向流程发送数据并捕获其输出时,它适合基本的子流程交互。
    • 示例:
      stdin, stdout, thr = IO.popen('some_command')
      
  2. IO.popen2

    • IO.popen2
      创建一个具有单独管道的子进程,用于标准输入和输出。
    • 它返回一个包含子进程的标准输入和输出流的数组。
    • 当您想要将数据发送到进程并单独捕获其输出时,它非常有用。
    • 示例:
      stdin, stdout = IO.popen2('some_command')
      
  3. IO.popen2e

    • IO.popen2e
      IO.popen2
      类似,但它将标准输出和标准错误流合并到单个流中。
    • 它返回一个数组,其中包含子进程的标准输入和组合的标准输出/错误流。
    • 当您想要同时捕获输出和错误消息时,这非常有用。
    • 示例:
      stdin, stdout_err = IO.popen2e('some_command')
      
  4. IO.popen3

    • IO.popen3
      创建一个子进程,其中包含用于标准输入、标准输出和标准错误的单独管道。
    • 它返回一个数组,其中包含子进程的标准输入、标准输出、标准错误和代表子进程的线程。
    • 它适用于需要与流程交互、捕获其输出并单独处理潜在错误消息的场景。
    • 示例:
      stdin, stdout, stderr, thr = IO.popen3('some_command')
      

何时使用每个版本取决于您的具体要求:

  • 当您需要与子流程的输入和输出交互并且不需要单独处理错误消息时,请使用

    IO.popen

  • 当您想要与标准输入分开捕获标准输出并需要将数据发送到进程时,请使用

    IO.popen2

  • 当您想要在单个流中同时捕获标准输出和标准错误时,请使用

    IO.popen2e

  • 当您需要单独的管道用于标准输入、标准输出和标准错误,并且希望与子进程交互并分别捕获输出和错误消息时,请使用

    IO.popen3


4
投票

要么做

IO.popen("ruby", "r+") do |pipe|
  pipe.puts "puts 10**6"
  pipe.puts "__END__"
  pipe.gets
end

或者做

IO.popen("irb", "r+") do |pipe|
  pipe.puts "\n"
  3.times {pipe.gets} # startup noise
  pipe.puts "puts 10**6\n"
  pipe.gets # prompt
  pipe.gets
end
© www.soinside.com 2019 - 2024. All rights reserved.