#!/usr/bin/perl # # Program to do a grep with dates and times on the debug # files # # grepdbg [nn] [-mm] # # nn - is the day you what to look at: 1 is yesterday, 0 is today # and is optional if there is only one argument # # -mmm - print the mmm lines before the match. So -3 will print # 4 lines altogether, the 3 lines before the line matching # the regular expression. # # is the regular expression you are searching for, # a caseless search is done. There can be more than one # a preceeded by a '!' is treated as NOT . Each # is implcitly ANDed together. # # If you specify something that likes a filename and that filename # has a .pm on the end of it and it exists then rather than doing # the regex match it executes the "main::handle()" function passing # it one line at a time. # # require 5.004; package main; # search local then perl directories BEGIN { # root of directory tree for this system $root = "/spider"; $root = $ENV{'DXSPIDER_ROOT'} if $ENV{'DXSPIDER_ROOT'}; unshift @INC, "$root/perl"; # this IS the right way round! unshift @INC, "$root/local"; } use SysVar; use DXUtil; use DXLog; use Julian; use strict; use vars qw(@days $fp $today $string); $fp = DXLog::new('debug', 'dat', 'd'); $today = $fp->unixtoj(time()); my $nolines = 1; my @prev; my @patt; foreach my $arg (@ARGV) { if ($arg =~ /^-/) { $arg =~ s/^-+//; if ($arg =~ /\?|^he?l?p?/) { usage(); exit(0); } $nolines += $arg if $arg =~ /^\d+$/; } elsif ($arg =~ /^\d+$/) { push @days, $arg; } elsif ($arg =~ /\.pm$/) { if (-e $arg) { my $fn = $arg; $fn =~ s/\.pm$//; eval { require $arg}; die "requiring $fn failed $@" if $@; die "required $fn does not contain 'sub handle' (check that 'package main;' exists)" unless main->can('handle'); } else { die "$arg not found"; } } else { push @patt, $arg; } } push @patt, '.*' unless @patt; push @days, "0" unless @days; for my $entry (@days) { my $now = $today->sub($entry); my $fh = $fp->open($now); my $line; my $do; begin() if main->can('begin'); if ($fh) { while (<$fh>) { if (main->can('handle')) { handle($_); } else { process($_); } } $fp->close(); } end() if main->can('end'); } total() if main->can('total'); exit 0; sub process { my $line = shift; chomp $line; push @prev, $line; shift @prev while @prev > $nolines; my $flag = 0; foreach my $p (@patt) { if ($p =~ /^!/) { my $r = substr $p, 1; last if $line =~ m{$r}i; } else { last unless $line =~ m{$p}i; } ++$flag; } if ($flag == @patt) { for (@prev) { s/([\x00-\x1f\x7f-\xff])/sprintf("\\x%02X", ord($1))/eg; my ($t, $l) = split /\^/, $_, 2; print atime($t), ' ', $l, "\n"; } print "------------------\n" if $nolines > 1; @prev = (); } } sub usage { print << "XXX"; usage: grepdbg [nn days before] [-nnn lines before] [] [|!]... You can have more than one with an implicit 'and' between them. All are caseless. It's recommended to put 'not' (!) first in any list. Don't forget that you are doing this in a shell and you may need to quote your s. grepdbg with no arguments will simply list the current debug log with the timestamp for each line decoded into a human readable form. grepdbg | less is a handy way of scrolling through the debug log. grepdbg -2 progress will display any line containing 'progress' and also the two lines before that. You can install your own content and display arrangement (useful for filtering data in some complicated way). You call it like this (assuming it is called 'filter.pm'). This is what is meant by . grepdbg filter.pm All the other arguments to grepdbg are available to limit the input to your filter. If you want them. The filter module MUST contain at least: package main; sub handle { your code goes here } 1; It can also have a 'sub begin {...}' and / or 'sub end {...}' which are executed immediately after opening a logfile and then just before closing it, respectively. You can also add a 'sub total {...}' which executes after the last line is printed and grepdbg exits. Read the code of this program and copy'n'paste the 'sub process' code into a new file. Then change 'sub process' to 'sub handle'. Add the line 'package main;' at the beginning of the file and a line '1;' at the end and then modify it to your requirements... XXX }