#!/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 -10 will print # ten lines including 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] [] [|!]... grepdbg with no argumants 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. 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'). 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 and its name to 'sub handle'. Modify it to your requirements... XXX }