【问题标题】:Running an interactive program from Ruby从 Ruby 运行交互式程序
【发布时间】:2014-12-28 04:58:50
【问题描述】:

我正在尝试从 ruby​​ 运行 gnuplot(不使用外部 gem)并解析其文本输出。我尝试了IO.popenPTY.spawnOpen3.popen3,但每当我尝试获取输出时,它只会“挂起”——我猜是在等待更多输出。我觉得它以某种方式使用Thread.new 完成了,但我找不到正确的方法来实现它。

有人知道它是怎么做的吗?

【问题讨论】:

  • 如果这是标准输出,请尝试通过 shell 命令获取它。将您的命令用反引号 (`command`) 或使用 %x(command)
  • 我正在尝试运行一个交互式程序。
  • 不知怎的,我错过了标题。对不起。你到底用Open3 尝试了什么?
  • i, o, e, th = Open3.popen3('gnuplot'); putc o.readchar while !o.eof?
  • 见“Extracting value from stdout of Open3.popen3 through RegEx and store it”,这很可能是这个问题的答案。

标签: ruby stdout popen interactive


【解决方案1】:

问题在于子程序正在等待未发送的输入。

通常,当我们调用一个期望在 STDIN 上输入的程序时,我们必须关闭 STDIN,然后通知该程序开始处理。查看各种Open3 方法,您会看到stdin.close 在许多示例中出现的位置,但它们没有解释原因。

Open3 还包括capture2capture3,这在尝试处理需要STDIN 并且您没有任何东西要发送给它的程序时非常好。在这两种方法中,STDIN 都会立即关闭,并返回被调用程序的 STDOUT、STDERR 和退出状态。


您需要“预期”功能。 Ruby 的 Pty 类包含一个 expect 方法。

创建和管理伪终端 (PTY)。另请参阅 en.wikipedia.org/wiki/Pseudo_terminal

虽然它没有很好的文档记录,并且没有提供我所看到的很多功能。 “Using Ruby Expect Library to Reboot Ruckus Wireless Access Points via ssh”提供了一个使用示例。

相反,您可能想查看RubyExpect,它有更好的文档记录并且似乎是最新的。

【讨论】:

  • 我不想匹配输出中的模式,我想在不阻塞输入的情况下完全得到它。
  • 对不起。这是一个更好的解决方案
  • 好的,当我通过标准输入发送命令并关闭它时,我可以读取标准输出和标准错误。但是我将如何重新打开标准输入以发送另一个命令?
  • 你没有。这就是为什么您需要“期望”来观察交互式响应,然后发送下一个输入。
  • 好吧,显然我错了。至少,正如托马斯建议的那样,我可以期待“gnuplot>”行。谢谢!
【解决方案2】:

我想这就是你想要的:

require 'pty'
require 'expect'

PTY.spawn('gnuplot') do |input, output, pid|
  str = input.expect(/gnuplot>/)
  puts str
  output.puts "mlqksdf"

  str = input.expect(/gnuplot>/)
  puts str
  output.puts "exit"
end

【讨论】:

    猜你喜欢
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    相关资源
    最近更新 更多