Code

convert PROGANE from a define to a const char
[nagiosplug.git] / contrib / check_log2.pl
1 #!/usr/bin/perl
2 #
3 # Log file regular expression detector for Nagios.
4 # Written by Aaron Bostick (abostick@mydoconline.com)
5 # Last modified: 05-02-2002
6 #
7 # Thanks and acknowledgements to Ethan Galstad for Nagios and the check_log
8 # plugin this is modeled after.
9 #
10 # Usage: check_log2 -l <log_file> -s <seek_file> -p <pattern> [-n <negpattern>]
11 #
12 # Description:
13 #
14 # This plugin will scan arbitrary text files looking for regular expression 
15 # matches.  The text file to scan is specified with <log_file>.
16 # <log_seek_file> is a temporary file used to store the seek byte position
17 # of the last scan.  This file will be created automatically on the first 
18 # scan.  <pattern> can be any RE pattern that perl's s/// syntax accepte.  Be
19 # forewarned that a bad pattern will send this script into never never land!
20 #
21 # Output:
22 #
23 # This plugin returns OK when a file is successfully scanned and no pattern
24 # matches are found.  WARNING is returned when 1 or more patterns are found 
25 # along with the pattern count and the line of the last pattern matched.
26 # CRITICAL is returned when an error occurs, such as file not found, etc.
27 #
28 # Notes (paraphrased from check_log's notes):
29 #
30 #    1.  The "max_attempts" value for the service should be 1, as this
31 #        will prevent Nagios from retrying the service check (the
32 #        next time the check is run it will not produce the same results).
33 #
34 #    2.  The "notify_recovery" value for the service should be 0, so that
35 #        Nagios does not notify you of "recoveries" for the check.  Since
36 #        pattern matches in the log file will only be reported once and not
37 #        the next time, there will always be "recoveries" for the service, even
38 #        though recoveries really don't apply to this type of check.
39 #
40 #    3.  You *must* supply a different <log_Seek_file> for each service that
41 #        you define to use this plugin script - even if the different services
42 #        check the same <log_file> for pattern matches.  This is necessary
43 #        because of the way the script operates.
44 #
45 # Examples:
46 #
47 # Check for error notices in messages
48 #   check_log2 -l /var/log/messages -s ./check_log2.messages.seek -p 'err'
49 #
52 BEGIN {
53     if ($0 =~ s/^(.*?)[\/\\]([^\/\\]+)$//) {
54         $prog_dir = $1;
55         $prog_name = $2;
56     }
57 }
59 require 5.004;
61 use lib $main::prog_dir;
62 use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
63 use Getopt::Long;
65 sub print_usage ();
66 sub print_version ();
67 sub print_help ();
69     # Initialize strings
70     $log_file = '';
71     $seek_file = '';
72     $re_pattern = '';
73     $neg_re_pattern = '';
74     $pattern_count = 0;
75     $pattern_line = '';
76     $plugin_revision = '$Revision$ ';
78     # Grab options from command line
79     GetOptions
80     ("l|logfile=s"      => \$log_file,
81      "s|seekfile=s"     => \$seek_file,
82      "p|pattern=s"      => \$re_pattern,
83      "n|negpattern:s"   => \$neg_re_pattern,
84      "v|version"        => \$version,
85      "h|help"           => \$help);
87     !($version) || print_version ();
88     !($help) || print_help ();
90     # Make sure log file is specified
91     ($log_file) || usage("Log file not specified.\n");
92     # Make sure seek file is specified
93     ($seek_file) || usage("Seek file not specified.\n");
94     # Make sure re pattern is specified
95     ($re_pattern) || usage("Regular expression not specified.\n");
97     # Open log file
98     open LOG_FILE, $log_file || die "Unable to open log file $log_file: $!";
100     # Try to open log seek file.  If open fails, we seek from beginning of
101     # file by default.
102     if (open(SEEK_FILE, $seek_file)) {
103         chomp(@seek_pos = <SEEK_FILE>);
104         close(SEEK_FILE);
106         #  If file is empty, no need to seek...
107         if ($seek_pos[0] != 0) {
108             
109             # Compare seek position to actual file size.  If file size is smaller
110             # then we just start from beginning i.e. file was rotated, etc.
111             ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat(LOG_FILE);
113             if ($seek_pos[0] <= $size) {
114                 seek(LOG_FILE, $seek_pos[0], 0);
115             }
116         }
117     }
119     # Loop through every line of log file and check for pattern matches.
120     # Count the number of pattern matches and remember the full line of 
121     # the most recent match.
122     while (<LOG_FILE>) {
123         if ($neg_re_pattern) {
124             if ((/$re_pattern/) && !(/$neg_re_pattern/)) {
125                 $pattern_count += 1;
126                 $pattern_line = $_;
127             }
128         } elsif (/$re_pattern/) {
129                 $pattern_count += 1;
130                 $pattern_line = $_;
131         }
132     }
134     # Overwrite log seek file and print the byte position we have seeked to.
135     open(SEEK_FILE, "> $seek_file") || die "Unable to open seek count file $seek_file: $!";
136     print SEEK_FILE tell(LOG_FILE);
138     # Close seek file.
139     close(SEEK_FILE);
140     # Close the log file.
141     close(LOG_FILE);
143     # Print result and return exit code.
144     if ($pattern_count) {
145         print "($pattern_count): $pattern_line";
146         exit $ERRORS{'WARNING'};
147     } else {
148         print "OK - No matches found.\n";
149         exit $ERRORS{'OK'};
150     }
153 # Subroutines
156 sub print_usage () {
157     print "Usage: $prog_name -l <log_file> -s <log_seek_file> -p <pattern> [-n <negpattern>]\n";
158     print "Usage: $prog_name [ -v | --version ]\n";
159     print "Usage: $prog_name [ -h | --help ]\n";
162 sub print_version () {
163     print_revision($prog_name, $plugin_revision);
164     exit $ERRORS{'OK'};
167 sub print_help () {
168     print_revision($prog_name, $plugin_revision);
169     print "\n";
170     print "Scan arbitrary log files for regular expression matches.\n";
171     print "\n";
172     print_usage();
173     print "\n";
174     print "-l, --logfile=<logfile>\n";
175     print "    The log file to be scanned\n";
176     print "-s, --seekfile=<seekfile>\n";
177     print "    The temporary file to store the seek position of the last scan\n";
178     print "-p, --pattern=<pattern>\n";
179     print "    The regular expression to scan for in the log file\n";
180     print "-n, --negpattern=<negpattern>\n";
181     print "    The regular expression to skip in the log file\n";
182     print "\n";
183     support();
184     exit $ERRORS{'OK'};