File: logtail

package info (click to toggle)
procmeter 2.4c-2
  • links: PTS
  • area: main
  • in suites: slink
  • size: 240 kB
  • ctags: 183
  • sloc: ansic: 1,927; perl: 140; makefile: 106; sh: 74
file content (132 lines) | stat: -rwxr-xr-x 3,738 bytes parent folder | download | duplicates (5)
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?
}