1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
#!/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?
}
|