3 # I have finally got sick of typing something like:
5 # tail -f logs/debug/2014/0623.log | grep -i mdip | grep -vi p[io]ng
7 # Do a tail -f of one of the current day's log files, the default is 'debug' but
8 # one can follow any of the others by putting enough of the directory
9 # as an argument so that it can find it eg:
11 # logf [perl regex] ...
12 # logf sys [perl regex] ...
13 # logf -100 [dir] [perl regex] ...
15 # NOTE: You can have many regexes and they all have to match (an implied '&&')
16 # NOTE: Also you preceed any regex with the '!' character to indicate negation (like "| grep -v regex")
18 # logf udpr - yields all udpr messages
19 # logf \!udpr - yields everything except udpr messages. Note the shell escape character
20 # logf udpr ping - yields udpr ping messages
21 # logf udpr \!p[io]ng - yields all udpr messages that aren't pings
23 # Copyright (c) 2014 Dirk Koopman, Tobit Computer Co Ltd
32 my $me = fileparse($0);
33 my $cwd = fileparse(getcwd);
38 if (@ARGV[0] =~ /^-[\?h]/) {
39 print "usage: $0 [-<count>] [<directory name fragment>] [<regex>]\n";
42 print " $0 -100 cdr\n";
44 print " $0 sys tcp\n";
45 print "\n any regexes are caseless\n\n";
46 print "default: $0 -40 debug\n";
51 my $lines = shift if ($ARGV[0] =~ /\-\d+/);
54 my $sort = shift || "debug";
58 opendir(my $dh, $base) or die "cannot open log directory '$base' ($!)";
59 @dirs = grep {!/^\./} readdir($dh);
63 my ($dir) = grep {/^$sort/} @dirs;
67 @pattern = ($sort, @ARGV);
71 my $s = IO::Select->new;
76 $SIG{TERM} = $SIG{INT} = sub {++$end};
80 my ($dd,$mm,$yy) = (gmtime)[3,4,5];
84 my $fn = sprintf "$base/$dir/%04d/%02d%02d", $yy, $mm, $dd;
87 } elsif (-e "$fn.csv") {
91 print "Waiting for $fn to appear...\n";
101 # open the file, seek to the end, then seek backward from the end a bit and start reading
102 # but ignore the first line 'cos it will be incomplete.
103 open I, $fn or die "cannot open $fn ($!)\n";
106 if ($pos <= int(abs($lines * 80))) {
109 seek(I, $pos + ($lines * 80), 0); # remember lines is (-)ve
112 my $buf; # input overflow buffer
137 if (wait_for_stdin(0.1)) {
139 print $state ? "\nRunning..." : "\nStopped...";
144 # runout any stored stuff if we haven't seen anything recently
145 if ($state && length $buf && ++$count > 2) {
147 print $buf if match($buf);scalar @pattern == grep $buf =~ m{$_}i, @pattern;
151 # print " *** XTRA! ***";
155 # move onto the next file if we roll over midnight
156 my ($d) = (gmtime)[3];
165 foreach my $p (@pattern) {
167 my $r = substr $p, 1;
168 last if $_[0] =~ m{$r}i;
170 last unless $_[0] =~ m{$p}i;
174 return $count == @pattern;
180 if ($s->can_read($t)) {