home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/perl
- # copyright: Joey Hess 1997 GPL.
-
- die q{
- Logtail watches one or more log files, and makes procmeter display graphs of
- how many lines are added to each file.
-
- Syntax:
- logtail filespec , [filespec , ... ] fifo
-
- fifo Basename of the fifo file to use to communicate with
- procmeter. The fifo.dat and fifo.def files will be created
- on the fly.
- filespec Specifies a file to watch and options for this file.
-
- Filespec Format:
-
- file=f units=u size=s pattern=p average=n rotate=[yes|no]
-
- file Watch the file specified. A required part of each
- filespec. This item is required.
- units The units to use (default: "lines")
- size How many lines in this file it takes to make one
- line on the graph (default: 1)
- name Name of this item on the graph (default: basename of file)
- pattern Pattern that the line must match to be counted. See perlre(1).
- (default: none specified, which matches everything)
- Note that if pattern contains a () grouping, then the
- value of that grouping is used for the value of the line.
- Useful for doing something like displayng stats on how many K
- are being transfered from your web server.
- rotate If "yes", try to figure out when the file is rotated, and
- recover from that condition. (default: yes)
-
- Example:
- logtail file=/var/log/httpd/access_log units=hits size=10 , \
- file=/var/log/messages rotate=yes size=2 \
- /tmp/logfifo
-
- } unless @ARGV;
-
- $fifo_basename=pop(@ARGV);
- $fifo="$fifo_basename.dat";
- system 'mkfifo',$fifo; # perl has no mkfifo command.
-
- open (DEF,">$fifo_basename.def") ||
- die "open $fifo.def failed: $!\n";
- my %filespec;
- my $spec_counter=0;
- foreach $word (@ARGV) {
- if ($word eq ',') {
- SaveFileSpec(%filespec);
- undef %filespec;
- }
- elsif ($word=~/(.*?)=(.*)/ ne undef) {
- $filespec{$1}=$2;
- }
- else {
- die "Unknown item found in filespec: $word\n";
- }
- }
- SaveFileSpec(%filespec);
- undef %filespec;
- close DEF;
-
- # Saves a filespec into global data hashes.
- sub SaveFileSpec { my %filespec=@_;
- my $filespec=$spec_counter++;
- if (!$filespec{file}) {
- die "Filespec does not contain file name.\n";
- }
-
- if (!$filespec{size}) {
- $filespec{size}=1;
- }
- if (!$filespec{name}) {
- ($filespec{name})=$filespec{file}=~m:.*/(.*?)$:;
- }
- if (!$filespec{units}) {
- $filespec{units}='lines';
- }
- if ($filespec{pattern}) {
- $log_pattern{$filespec}=$filespec{pattern};
- }
- open ($filespec,"<$filespec{file}")
- || die "open $filespec{file} failed: $!\n";
- seek($filespec,0,2); # seek to eof.
- $log_counter{$filespec}=0;
- $log_filesize{$filespec}=-s $filspec{name};
- $log_filename{$filespec}=$filespec{file};
- print DEF "$filespec{name} $filespec{units} " .
- $filespec{size} . "\n";
- if ($filespec{rotate} eq 'yes') {
- $rotate_protect{$filespec}=1;
- }
- }
-
- for (;;) {
- foreach $filespec (keys %log_counter) {
- if ($rotate_protect && -r $log_filename{$filespec}) {
- if (-s $log_filename{$filespec} < $log_filesize{$filespec}) {
- # File size has decreased, assume the file has been
- # rotated on us.
- close $filespec;
- open ($filespec,"<$log_filename{$filespec}");
- seek($filespec,0,2); # seek to eof.
- }
- $log_filesize{$filespec}=-s $log_filename{$filespec};
- }
- while (!eof($filespec)) {
- $_=<$filespec>;
- if (! $log_pattern{$filespec} ||
- m/$log_pattern{$filespec}/ ne undef) {
- if ($1) {
- $log_counter{$filespec} += $1;
- }
- else {
- $log_counter{$filespec} += 1;
- }
- }
- }
- }
-
- open (OUT,">$fifo") || die;
- foreach $filespec (keys %log_counter) {
- print OUT "$log_counter{$filespec}\n";
- $log_counter{$filespec}=0;
- }
- close OUT;
-
- select(undef,undef,undef,0.25); # why is this needed?
- }
-