So many times while watching log files I wanted to find a command that combines tail with grep filtering functionally. The Unix command repository is huge and I'm pretty sure you can do it without resorting to a scripting language. But having spent several minutes googling for this functionality to no avail, I decided to bring Ruby to the rescue.
At first I thought that I had to port File::Tail Perl module to Ruby, but I found that it has been done already by Florian Frank. He has even provided a convenient way of installing it:
$ sudo gem install file-tail
OK, the rest was as obvious as this:
$ cat tailg
#!/usr/bin/env ruby
require 'rubygems'
gem 'file-tail'
require 'file/tail'
if ARGV.size != 2
$stderr.puts "Usage #$0 <regexp> <log-file>"
end
begin
File.open(ARGV[1]) do |log|
log.extend(File::Tail)
log.interval = 2
log.backward(10)
log.tail { |line| puts line if line =~ /#{ARGV[0]}/ }
end
rescue Exception
end
$./tailg 'products' /var/log/searchd_query.log
[Sat Mar 3 13:39:40 2007] 0.000 sec [all/0/rel 3 (0,9)] [products] NOA
[Sat Mar 3 13:39:44 2007] 0.000 sec [all/0/rel 22 (0,9)] [products] lauren
[Sat Mar 3 13:40:09 2007] 0.000 sec [all/0/rel 22 (9,9)] [products] lauren
tailg command accepts two parameters: a regexp to filter for interesting lines and a log file itself.
You can combine tail with grep with a regular unix pipe.
tail file | grep pattern
tail file | grep -e regex
Or to continually monitor updates:
tail file -f | grep pattern
I knew there is a better way! I've never realized that it's possible to pipe tail -f like that. Very nice. Thanks.
File::Tail has some cool stuff people don't usually recognize. For instance, if a file is removed and replaced with a new one with the same name (say, during logfile rotation), tail -f would halt, but File::Tail would continue to read the file.
Of course, GNU tail can do it too:
tail -F file |grep pattern