如何在ruby中解析和处理实时输出?

时间:2015-07-29 19:23:55

标签: ruby bash stream tail

我想在ruby中做一件简单的事情:进入服务器,在日志文件上启动tailf -f命令,并对输出流执行一些操作。 (比如提取一些信息)

我怎么能在ruby中做到?

如果使用反引号来执行命令,它的输出永远不会返回,是否有一个旧的连续输出的数据结构?

3 个答案:

答案 0 :(得分:1)

最简单的方法(以及大多数Unix-y方式)是使用-n命令的-pruby参数。从手册页(man ruby):

-n     Causes Ruby to assume the following loop around your script, which makes
       it iterate over file name arguments somewhat like sed -n or awk.

             while gets
               ...
             end

这是模糊的(并且“文件名参数”位有误导性),所以这是一个例子(让我们称之为sum.rb):

BEGIN {
  sum = 0
}

sum += $_.to_i

END {
  puts "Sum: #{sum}"
}

当我们使用ruby -n运行此脚本时会发生什么情况,BEGIN块中的代码将运行一次,然后块外的代码将针对通过管道传输给Ruby的每一行输入运行该行存储在$_中 - 然后END块中的代码将会运行。

假设我们有一个包含以下内容的文件(让我们称之为data.txt):

10
15
25
50

现在我们可以这样做:

$ cat data.txt | ruby -n sum.rb
Sum: 100

如果我们只想总结前两个数字怎么办?使用head

$ head -2 data.txt | ruby -n sum.rb
Sum: 25

如果我们想打印除了总和之外的每个数字怎么办?使用-p(代表“打印”)代替-n

$ head -2 data.txt | ruby -p sum.rb
10
15
Sum: 25

ruby命令非常强大。例如,-a选项将 a 将每行自动拆分为数组并将其放入$F,因此如果您的输入有两列,则每行的第一列将在$F[0]$F[1]中的第二个,依此类推。我强烈建议您输入man ruby并花几分钟时间查看可用的选项。这是一篇很好的博客文章,其中介绍了一些功能:http://arjanvandergaag.nl/blog/using-ruby-command-line-options.html

最后一件事:为了便于使用,我建议在脚本顶部添加一个shebang行,例如:

#!/usr/bin/env ruby -n

...然后使用chmod使您的脚本可执行(例如chmod ug+x sum.rb)。通过这种方式,您的脚本可以指定所需的所有参数,您只需执行cat data.txt | ./sum.rb

答案 1 :(得分:0)

您可以使用pty模块。

你需要做这样的事情:

require 'pty'

cmd = "tail -f <path-to-your-log-file>"

begin
  PTY.spawn(cmd) do |stdout, stdin, pid|
    begin
      # print output to show how it works
      # you will need to extract your info from "line" variable below
      stdout.each { |line| print line }
    rescue Errno::EIO
      puts "This means the process has finished giving output"
    end
  end
rescue PTY::ChildExited
  puts "Child process exited!"
end

答案 2 :(得分:0)

f=File.open("path_to_log_file")
no_of_lines_per_fetch = 1
f.seek(0, no_of_lines_per_fetch)

def decision_making_function(data)
  #your logic
  puts "processing #{data}"
end

while true
  if (line=f.gets) != nil
    decision_making_function(line)
  end
end