#!/usr/bin/perl # # $Id: ptail,v 1.12 2003/08/01 02:10:56 jmates Exp $ # # The author disclaims all copyrights and releases this script into the # public domain. # # Run perldoc(1) on this file for additional documentation. # ###################################################################### # # REQUIREMENTS require 5; # disabled to allow more flexible expression composition #use strict; ###################################################################### # # MODULES use Carp; # better error reporting use Getopt::Std; # command line option processing use File::Tail; # tail -f on steroids ###################################################################### # # VARIABLES my $VERSION; ($VERSION = '$Revision: 1.12 $ ') =~ s/[^0-9.]//g; my (%opts, $filename, $file); # various File::Tail object preferences. listen much faster than default # to emulate tail(1) at expense of more busy wait. my $maxinterval = 2; my $interval = 1; my $adjustafter = 1; my $tail = 0; my $reset_tail = -1; # default to just printing input my $expression = "print"; # commands to be executed before entring the loop my $preop = ""; ###################################################################### # # MAIN # parse command-line options getopts('h?m:i:a:t:r:p:', \%opts); help() if exists $opts{'h'} or exists $opts{'?'} or not @ARGV; $maxinterval = $opts{'m'} if exists $opts{'m'} and $opts{'m'} =~ /^\d+$/; $interval = $opts{'i'} if exists $opts{'i'} and $opts{'i'} =~ /^\d+$/; $adjustafter = $opts{'a'} if exists $opts{'a'} and $opts{'a'} =~ /^\d+$/; $tail = $opts{'t'} if exists $opts{'t'} and $opts{'t'} =~ /^-?\d+$/; $reset_tail = $opts{'r'} if exists $opts{'r'} and $opts{'r'} =~ /^-?\d+$/; $preop = $opts{'p'} if exists $opts{'p'}; # filename to tail on and perl expression to apply to each line $filename = shift; $expression = "@ARGV" if @ARGV; $file = File::Tail->new( name => $filename, maxinterval => $maxinterval, interval => $interval, adjustafter => $adjustafter, tail => $tail, reset_tail => $reset_tail, ); # don't buffer STDOUT soas to interoperate with tee(1) properly $| = 1; # handle anything that needs to be done first eval $preop; die 'Preop failed: ', $@, if $@; # loop forever on file; apply supplied expression to each line while (defined($_ = $file->read)) { eval $expression; die 'Expression error: ', $@ if $@; } exit; ###################################################################### # # SUBROUTINES # a generic help blarb sub help { print <<"HELP"; Usage: $0 [opts] file [expression] tails a file and applies perl expression to each line Options for version $VERSION: -h/-? Display this message -p exp Code to be executed before entering loop. -m sec Check file for updates this often at most. -i sec Initial sleep period before checking file. -a sec Times to wait until adjusting check interval. -t num Read num lines from file. Negative is whole file. -r num Lines to read after file reset. Run perldoc(1) on this script for additional documentation. HELP exit; } ###################################################################### # # DOCUMENTATION =head1 NAME ptail - follows a file and applies a perl expression to each line =head1 SYNOPSIS Follow a logfile, and print any lines mentioning ipmon: $ ptail /var/log/messages print if m/ipmon/ See L<"EXAMPLES"> for more ideas. =head1 DESCRIPTION =head2 Overview This script is the functional equivalent of the tail(1) utility running in follow mode, with the additional ability to apply an arbitrary perl expression to each line seen in the file being tracked. The primary use seen for this script is to extract out and manipulate specific lines of interest from a busy logfile. =head2 Normal Usage $ ptail [options] file [expression] See L<"OPTIONS"> for details on the command line switches supported. The file to watch is required, and the expression defaults to "print" to emulate the behaviour of a C. The expression is built from any number of arguments following the file, for greater flexibility. $_ is used to store each line in turn. =head1 OPTIONS This script currently supports the following command line switches: =over 4 =item B<-h>, B<-?> Prints a brief usage note about the script. =item B<-p> I Perl expression to be executed before entering the loop on the file. Use to perform any initial one-time operations one might need. =item B<-m> I (maxinterval) Check file for updates this often at most. =item B<-i> I (interval) Initial sleep period before checking file. =item B<-a> I (adjustafter) Times to wait until adjusting check interval. =item B<-t> I (tail) Read num lines from file. Negative is whole file. =item B<-r> I (reset_tail) Lines to read after file reset. =back See L for more information on the parenthesized parameter names, which are File::Tail parameters passed directy to the object. =head1 EXAMPLES Walk through all of C before following the file, printing lines pertaining to dhcpd: $ ptail -t -1 /var/log/messages 'print if m/ dhcpd/' Watch for the ip address 10.0.0.1 in C, triming the standard syslog leading information, and saving a copy of the data to C: $ ptail /var/log/system.log 's/^\w{3}\s+\d+ [\d:]+ \w+ //; \ print if m/\Q10.0.0.1\E/' | tee /tmp/10.log =head1 BUGS =head2 Reporting Bugs Newer versions of this script may be available from: http://sial.org/code/perl/ If the bug is in the latest version, send a report to the author. Patches that fix problems or add new features are welcome. =head2 Known Issues No known bugs. =head1 SEE ALSO File::Tail, perl(1), tee(1) =head1 AUTHOR Jeremy Mates, http://sial.org/contact/ =head1 COPYRIGHT The author disclaims all copyrights and releases this script into the public domain. =head1 VERSION $Id: ptail,v 1.12 2003/08/01 02:10:56 jmates Exp $ =head1 SCRIPT CATEGORIES Utilities UNIX/System_administration =cut