6

There were a number of other threads like this, but the usual conclusion was something like "Install File::Tail". But, I'm on an old box that we're decomissioning, and I just want to write a one-liner to monitor a log. I tried installing File::Tail, but the environment for CPAN just isn't working, and I don't want to take the time to figure out what the problem is.

I just want a basic script that parses out an IP address and keeps a count of it for me. For some reason, though, even this simple test doesn't work:

$ tail -f snmplistener.log|grep IPaddress |perl -ne 'print "LINE: $_\n";'

I think it has something to do with output buffering, but I've always been a bit fuzzy on how that works. How can I get this one-liner working?

coding_hero
  • 1,759
  • 3
  • 19
  • 34
  • It's not output buffering - it's input buffering. Perl won't read from stdin automatically, you'd need a `while(<>) { echo $_ }` type thing going. – Marc B Nov 09 '11 at 19:20
  • False economy. If CPAN doesn't work, you can always [download the distro](http://search.cpan.org/CPAN/authors/id/M/MG/MGRABNAR/File-Tail-0.99.3.tar.gz) and [install it manually](http://p3rl.org/modinstall). – daxim Nov 09 '11 at 19:21
  • 1
    Do you have that problem if you remove `grep(1)` and just `perl -lne 'print "LINE: $_" if /IPaddress/'` ? – pilcrow Nov 09 '11 at 19:22
  • 2
    @MarcB, the `-n` adds a `while (<>) { ... }` around the provided code. – cjm Nov 09 '11 at 19:23
  • 1
    @MarcB - he's thrown the `-n` flag. Perl will read from `<>` automatically :) – pilcrow Nov 09 '11 at 19:23

3 Answers3

10

tail -f doesn't generally buffer output, but grep probably does. Move the "grep" functionality into your Perl one-liner:

tail -f snmplistener.log | perl -ne 'print "LINE: $_\n" if /IPaddress/'
mob
  • 117,087
  • 18
  • 149
  • 283
  • I've never seen gnu grep buffer output. tail -f|grep on an apache logfile always shows up the grepped lines immediately. – Marc B Nov 09 '11 at 19:24
  • Oh, DUH. Ok, it works now. Marking you as answerer in 2 minutes. – coding_hero Nov 09 '11 at 19:27
  • @MarcB, probably because output to a terminal is line-buffered by default, so you'd see it when tailing logs on the console. Try `tail | grep | cat -` or similar. Related, it's GNU grep, I believe, that supports the `--line-buffered` switch. :) – pilcrow Nov 09 '11 at 19:30
2

man grep

--line-buffered
      Use line buffering on output.  This can cause a performance penalty.

so:

tail -f /log/file.txt | grep --line-buffered SomePattern | perl ...
Yuck
  • 49,664
  • 13
  • 105
  • 135
Henrik
  • 21
  • 1
1

Or without using tail at all:

perl -e 'open($h,$ARGV[0]); while (1) { /IPaddress/ and print "LINE: $_" for <$h>; sleep 1 }' snmplistener.log
MisterEd
  • 1,725
  • 1
  • 14
  • 15