Conditional tail

Posted on March 03, 2007

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.

Comments
  1. evanMarch 04, 2007 @ 12:01 AM

    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

  2. KentMarch 04, 2007 @ 03:32 AM

    I knew there is a better way! I've never realized that it's possible to pipe tail -f like that. Very nice. Thanks.

  3. JustinApril 13, 2007 @ 05:15 PM

    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