Reputation: 3338
I would like to do a simple thing in ruby: enter in a server , launch a tailf -f
command on a log file, and perform some operation on the stream of output. (like extract some info)
How can I do it in ruby?
If a use the backtick to execute the command, the output it is never returned, is there a data structure to old this continuos output?
Upvotes: 0
Views: 844
Reputation: 2895
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
Upvotes: 0
Reputation: 106027
The easiest way (and most Unix-y way) is to use the -n
or -p
arguments to the ruby
command. From the man page (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
That's vague (and the "file name arguments" bit is misleading), so here's an example (let's call it sum.rb
):
BEGIN {
sum = 0
}
sum += $_.to_i
END {
puts "Sum: #{sum}"
}
What will happen when we run this script with ruby -n
is, the code in the BEGIN
block will run once, then the code outside the block will run for every line of input piped to Ruby—the line is stored in $_
—and then the code in the END
block will run.
Suppose we have a file with the following content (let's call it data.txt
):
10
15
25
50
Now we can do this:
$ cat data.txt | ruby -n sum.rb
Sum: 100
What if we only want to sum the first two numbers? Use head
!
$ head -2 data.txt | ruby -n sum.rb
Sum: 25
What if we want to print every number, in addition to the sum? Use -p
(for "print") instead of -n
:
$ head -2 data.txt | ruby -p sum.rb
10
15
Sum: 25
The ruby
command is very powerful. For example, the -a
option will automatically split each line into an array and put it in $F
, so if your input has two columns the first column of each line will be in $F[0]
, the second in $F[1]
, and so on. I highly recommend typing man ruby
and taking a few minutes to see what options are available. Here's a good blog post that goes over some of the features: http://arjanvandergaag.nl/blog/using-ruby-command-line-options.html
One last thing: For ease of use, I recommend adding a shebang line to the top of your script, e.g.:
#!/usr/bin/env ruby -n
...and then using chmod
to make your script executable (e.g. chmod ug+x sum.rb
). This way your script can specify all of the arguments it needs and you can just do cat data.txt | ./sum.rb
.
Upvotes: 1
Reputation: 6957
You can use the pty module.
You will need to do something like this:
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
Upvotes: 0