Messy apache error logs got you down? Squinting so hard trying to look through all the repeated information that's not useful that you're leaving visible marks on your eyeballs? No longer. Use err_watch and watching your error log will be more fun than TV! It helps you strip out all the redundant information and shows only what is left: relevent things. Run with -h for switching options. Features requests appreciated.
#!/usr/bin/perl -w # usage information found at the bottom or by using -h use strict; use Term::ReadKey; use Time::Local; use Cwd qw(abs_path); $|++; my (%Options, $wchar, $hchar); sub get_options; sub printNice($); sub mon2num($); sub timelocal_str; sub bufferstr; main: { %Options = get_options(); my $ph; if( $Options{watch_file} && $Options{watch_file} ne '-' ) { + eval { open LOG, qq{tail -n0 -f "$Options{watch_file}"|} } or +die "Couldn't open pipe to tail: $!"; local $SIG{PIPE} = sub { die "tail pipe broke" }; $ph = \*LOG; } else { $ph = \*STDIN; } my $cur; my $lastcur = 0; while( <$ph> ) { chomp; if( /^\[([^\]]+)\]/ ) { ($wchar, $hchar, ) # $wpixels, $hpixels) = GetTerminalSize(); my $lt = timelocal_str($1); if( $lt >= $cur + $Options{group_sec}) { $lastcur = $cur = $lt; print bufferstr() . localtime($lt) . ":\n"; } if( $Options{show_times} && $lt != $lastcur ) { $lastcur = $lt; print( (' 'x($Options{indent} - 4)) . localtime($lt) . + "\n"); } s/^\[[^\]]+\]//; s/\s*\[error\]\s*// if( $Options{error} ); s/\s*\[client [^\]]+\]\s*// if( $Options{client} ); s/, referer: .*// if( $Options{referer} ); foreach my $str ( @{ $Options{dir_filter} } ) { s/$str//g; } printNice "$_\n"; } } close LOG; } sub printNice($) { my $str = shift; print join('', ' 'x($Options{indent})) . '* ' . substr($str, 0, $w +char - $Options{indent} -3, ''); while($str ne '') { print "\n" . join('', ' 'x($Options{indent}+2)) . substr($str, + 0, $wchar - $Options{indent} - 2 -1, ''); } } sub mon2num($) { my $month = shift; my %h = qw( jan 0 feb 1 mar 2 apr 3 may 4 jun 5 jul 6 aug 7 sep 8 oct 9 nov 10 dec 11 ); return $h{ lc substr($month, 0, 3) }; } sub timelocal_str { #does the opposite of localtime, my $seconds = tim +elocal( localtime().'' ) my ($str) = @_; # Sat Jan 21 01:16:50 2006 $str =~ s/\s+|\s+/ /g; $str =~ s/^\s+/ /g; $str =~ s/\s+$/ / +g; my ($wd, $mon, $mday, $hr, $min, $sec, $yr) = split /[ \:]/, $str; return timelocal($sec, $min, $hr, $mday, mon2num $mon, $yr); } sub bufferstr { my $buffer = ''; if( $Options{buffer} ) { my $buffer_line = ''; while( length($buffer_line) + length($Options{buffer}) < $wcha +r ) { $buffer_line .= $Options{buffer}; } $buffer .= $buffer_line; } $buffer .="\n"x($hchar + 1); return $buffer; } sub get_options { my %options = ( 'referer' => 1, 'client' => 1, 'error' => 1, 'dir_filter' => [], 'indent' => 6, 'group_sec' => 2, 'show_times' => undef, 'watch_file' => q{-}, 'buffer' => q{ == - == -}, ); while( $_ = shift @ARGV ) { my $had_unshift = 0; if( /^-[a-z0-9]{2,}/i ) { my $param = substr($_, 0, 2, ''); my ($p, $v) = split /=/; unshift @ARGV, $v if( $v ); foreach my $n ( reverse split //, $p ) { unshift @ARGV, "-$n"; } $_ = $param; } elsif( /=/ ){ my ($k, $v) = split /=/, $_, 2 ; $_ = $k; unshift @ARGV, $v; $had_unshift = 1; } if( /--help|-h/ ) { print usage(); exit(1); } elsif( /--referer|-r/ ) { $options{referer} = 0; } elsif( /--client|-c/ ) { $options{client} = 0; } elsif( /--error|-e/ ) { $options{error} = 0; } elsif( /--dir|-d/ ) { my $d = shift(@ARGV) || '.' ; my $rel_d; eval { $rel_d = abs_path($d) }; #bad paths are OK. $d = $rel_d if $rel_d; push @{ $options{dir_filter} }, $d ; } elsif( /--indent|-i/ ) { $options{indent} = shift(@ARGV); } elsif( /--group-sec|-t/ ) { $options{group_sec} = shift(@ARGV); } elsif( /--buffer|-B/ ) { $options{buffer} = shift(@ARGV); } elsif( /--show-times|-s/ ) { $options{show_times} = 1; } else { $options{watch_file} = $_; } } return %options; } sub usage { return q{ err_watch [-rce] [-d=dir]* [-i=n] [-t=sec] [-B=str] [watched_file] -r,--referer Leave the referer line in the log -c,--client Leave the [client ...] info in the log -e,--error Leave the [error] info in the log -d=dir,--dir Filter out the string matching dir or the current directory (filename collap +sing), this option may be given multiple times -i=n,--indent Indent the contents of the watched file by +n spaces -t=sec,--group-sec Group errors in sec seconds icrements -B=str,--buffer The string defining your "group buffer stri +ng" it will print 1 row of these repating all + the way across. -s,--show-times if set, it will print a timestamp starting +wherever the logged timestamp changes, it will sti +ll group them according to -t however }; }

In reply to err_watch for when your errors are growing like hair or... by qbxk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.