Code

f3f6f78bb9898863608960ed3ef960b9547a6470
[nagiosplug.git] / plugins-scripts / check_ntp.pl
1 #! /usr/bin/perl -wT
3 # (c)1999 Ian Cass, Knowledge Matters Ltd.
4 # Read the GNU copyright stuff for all the legalese
5 #
6 # Check NTP time servers plugin. This plugin requires the ntpdate utility to
7 # be installed on the system, however since it's part of the ntp suite, you 
8 # should already have it installed.
9 #
10 # Nothing clever done in this program - its a very simple bare basics hack to
11 # get the job done.
12 #
13 # Things to do...
14 # check @words[9] for time differences greater than +/- x secs & return a
15 # warning.
16 #
17 # (c) 1999 Mark Jewiss, Knowledge Matters Limited
18 # 22-9-1999, 12:45
19 #
20 # Modified script to accept 2 parameters or set defaults.
21 # Now issues warning or critical alert is time difference is greater than the 
22 # time passed.
23 #
24 # These changes have not been tested completely due to the unavailability of a
25 # server with the incorrect time.
26 #
27 # (c) 1999 Bo Kersey, VirCIO - Managed Server Solutions <bo@vircio.com>
28 # 22-10-99, 12:17
29 #
30 # Modified the script to give useage if no parameters are input.
31 #
32 # Modified the script to check for negative as well as positive 
33 # time differences.
34 #
35 # Modified the script to work with ntpdate 3-5.93e Wed Apr 14 20:23:03 EDT 1999
36 #
37 # Modified the script to work with ntpdate's that return adjust or offset...
38 #
39 #
40 # Script modified 2000 June 01 by William Pietri <william@bianca.com>
41 #
42 # Modified script to handle weird cases:
43 #     o NTP server doesn't respond (e.g., has died)
44 #     o Server has correct time but isn't suitable synchronization
45 #           source. This happens while starting up and if contact
46 #           with master has been lost.
47 #
48 BEGIN {
49         if ($0 =~ m/^(.*?)[\/\\]([^\/\\]+)$/) {
50                 $runtimedir = $1;
51                 $PROGNAME = $2;
52         }
53 }
55 require 5.004;
56 use POSIX;
57 use strict;
58 use Getopt::Long;
59 use vars qw($opt_V $opt_h $opt_H $opt_w $opt_c $verbose $PROGNAME);
60 use lib $main::runtimedir;
61 use utils qw($TIMEOUT %ERRORS &print_revision &support);
63 sub print_help ();
64 sub print_usage ();
66 $ENV{'PATH'}='';
67 $ENV{'BASH_ENV'}='';
68 $ENV{'ENV'}='';
70 Getopt::Long::Configure('bundling');
71 GetOptions
72         ("V"   => \$opt_V, "version"    => \$opt_V,
73          "h"   => \$opt_h, "help"       => \$opt_h,
74          "v" => \$verbose, "verbose"  => \$verbose,
75          "w=s" => \$opt_w, "warning=s"  => \$opt_w,
76          "c=s" => \$opt_c, "critical=s" => \$opt_c,
77          "H=s" => \$opt_H, "hostname=s" => \$opt_H);
79 if ($opt_V) {
80         print_revision($PROGNAME,'$Revision$ ');
81         exit $ERRORS{'OK'};
82 }
84 if ($opt_h) {
85         print_help();
86         exit $ERRORS{'OK'};
87 }
89 $opt_H = shift unless ($opt_H);
90 my $host = $1 if ($opt_H && $opt_H =~ m/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z][-a-zA-Z0-9]+(\.[a-zA-Z][-a-zA-Z0-9]+)*)$/);
91 unless ($host) {
92         print_usage();
93         exit $ERRORS{'UNKNOWN'};
94 }
96 ($opt_w) || ($opt_w = shift) || ($opt_w = 60);
97 my $warning = $1 if ($opt_w =~ /([0-9]+)/);
99 ($opt_c) || ($opt_c = shift) || ($opt_c = 120);
100 my $critical = $1 if ($opt_c =~ /([0-9]+)/);
102 my $answer = undef;
103 my $offset = undef;
104 my $msg; # first line of output to print if format is invalid
106 my $state = $ERRORS{'UNKNOWN'};
107 my $ntpdate_error = $ERRORS{'UNKNOWN'};
108 my $dispersion_error = $ERRORS{'UNKNOWN'};
110 my $key = undef;
112 # Just in case of problems, let's not hang Nagios
113 $SIG{'ALRM'} = sub {
114         print ("ERROR: No response from ntp server (alarm)\n");
115         exit $ERRORS{"UNKNOWN"};
116 };
117 alarm($TIMEOUT);
120 ###
121 ###
122 ### First, check ntpdate
123 ###
124 ###
126 if (!open (NTPDATE, "/usr/local/sbin/ntpdate -q $host 2>&1 |")) {
127         print "Could not open ntpdate\n";
128         exit $ERRORS{"UNKNOWN"};
131 while (<NTPDATE>) {
132         print if ($verbose);
133         $msg = $_ unless ($msg);
134         if (/(offset|adjust)\s+([-.\d]+)/i) {
135                 $offset = $2;
136                 last;
137         }
140 # soak up remaining output; check for error
141 while (<NTPDATE>) {
142         if (/no server suitable for synchronization found/) {
143                 $ntpdate_error = $ERRORS{"CRITICAL"};
144         }
147 close(NTPDATE);
149 # only declare an error if we also get a non-zero return code from ntpdate
150 $ntpdate_error = ($? >> 8) || $ntpdate_error;
152 ###
153 ###
154 ### Then scan xntpdc if it exists
155 ###
156 ###
158 if (#open(NTPDC,"/usr/sbin/ntpdc -c $host 2>&1 |") ||
159     open(NTPDC,"/usr/sbin/xntpdc -c $host 2>&1 |") ) {
160         while (<NTPDC>) {
161                 print if ($verbose);
162                 if (/([^\s]+)\s+([-0-9.]+)\s+([-0-9.]+)\s+([-0-9.]+)\s+([-0-9.]+)\s+([-0-9.]+)\s+([-0-9.]+)\s+([-0-9.]+)/) {
163                         if ($8>15) {
164                                 $dispersion_error = $ERRORS{'CRITICAL'};
165                         } elsif ($8>5 && $dispersion_error<$ERRORS{'CRITICAL'}) {
166                                 $dispersion_error = $ERRORS{'WARNING'};
167                         }
168                 }
169         }
170         close NTPDC;
173 # An offset of 0.000000 with an error is probably bogus. Actually,
174 # it's probably always bogus, but let's be paranoid here.
175 if ($ntpdate_error && $offset && ($offset == 0)) { undef $offset;}
177 if ($ntpdate_error > $ERRORS{'OK'}) {
178         $state = $ntpdate_error;
179         $answer = "Server for ntp probably down\n";
180         if (defined($offset) && abs($offset) > $critical) {
181                 $state = $ERRORS{'CRITICAL'};
182                 $answer = "Server Error and time difference $offset seconds greater than +/- $critical sec\n";
183         } elsif (defined($offset) && abs($offset) > $warning) {
184                 $answer = "Server error and time difference $offset seconds greater than +/- $warning sec\n";
185         }
187 } elsif ($dispersion_error > $ERRORS{'OK'}) {
188         $state = $dispersion_error;
189         $answer = "Dispersion too high\n";
190         if (defined($offset) && abs($offset) > $critical) {
191                 $state = $ERRORS{'CRITICAL'};
192                 $answer = "Dispersion error and time difference $offset seconds greater than +/- $critical sec\n";
193         } elsif (defined($offset) && abs($offset) > $warning) {
194                 $answer = "Dispersion error and time difference $offset seconds greater than +/- $warning sec\n";
195         }
197 } else { # no errors from ntpdate or xntpdc
198         if (defined $offset) {
199                 if (abs($offset) > $critical) {
200                         $state = $ERRORS{'CRITICAL'};
201                         $answer = "Time difference $offset seconds greater than +/- $critical sec\n";
202                 } elsif (abs($offset) > $warning) {
203                         $state = $ERRORS{'WARNING'};
204                         $answer = "Time difference $offset seconds greater than +/- $warning sec\n";
205                 } elsif (abs($offset) <= $warning) {
206                         $state = $ERRORS{'OK'};
207                         $answer = "Time difference $offset seconds\n";
208                 }
209         } else { # no offset defined
210                 $state = $ERRORS{'UNKNOWN'};
211                 $answer = "Invalid format returned from ntpdate ($msg)\n";
212         }
215 foreach $key (keys %ERRORS) {
216         if ($state==$ERRORS{$key}) {
217                 print ("$key: $answer");
218                 last;
219         }
221 exit $state;
223 sub print_usage () {
224         print "Usage: $PROGNAME -H <host> [-w <warn>] [-c <crit>]\n";
227 sub print_help () {
228         print_revision($PROGNAME,'$Revision$');
229         print "Copyright (c) 2000 Bo Kersey/Karl DeBisschop\n";
230         print "\n";
231         print_usage();
232         print "\n";
233         print "<warn> = Clock offset in seconds at which a warning message will be generated.\n Defaults to 60.\n";
234         print "<crit> = Clock offset in seconds at which a critical message will be generated.\n        Defaults to 120.\n\n";
235         support();