File check_rsync of Package nagios-plugins-rsync
x
1
#!/usr/bin/perl
2
#
3
# check_rsync - Check Rsync and modules availability
4
# Version: 1.02
5
#
6
# Copyright (C) 2006-2008 Thomas Guyot-Sionnest <tguyot@gmail.com>
7
#
8
# This program is free software; you can redistribute it and/or
9
# modify it under the terms of the GNU General Public License
10
# as published by the Free Software Foundation; either version 2
11
# of the License, or (at your option) any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, write to the Free Software
20
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
#
22
23
use POSIX;
24
use strict;
25
use Getopt::Long;
26
27
use vars qw($opt_H $opt_p $opt_m);
28
use vars qw($PROGNAME %RSYNCMSG $cpid);
29
use lib "/usr/local/nagios/libexec";
30
use utils qw($TIMEOUT %ERRORS);
31
32
$PROGNAME = "check_rsync";
33
$ENV{'PATH'}='';
34
$ENV{'BASH_ENV'}='';
35
$ENV{'ENV'}='';
36
%RSYNCMSG = (
37
'0' => 'Success',
38
'1' => 'Syntax or usage error',
39
'2' => 'Protocol incompatibility',
40
'3' => 'Errors selecting input/output files, dirs',
41
'4' => 'Requested action not supported',
42
'5' => 'Error starting client-server protocol',
43
'6' => 'Daemon unable to append to log-file',
44
'10' => 'Error in socket I/O',
45
'11' => 'Error in file I/O',
46
'12' => 'Error in rsync protocol data stream',
47
'13' => 'Errors with program diagnostics',
48
'14' => 'Error in IPC code',
49
'20' => 'Received SIGUSR1 or SIGINT',
50
'21' => 'Some error returned by waitpid()',
51
'22' => 'Error allocating core memory buffers',
52
'23' => 'Partial transfer due to error',
53
'24' => 'Partial transfer due to vanished source files',
54
'25' => 'The --max-delete limit stopped deletions',
55
'30' => 'Timeout in data send/receive',
56
);
57
$cpid = 0;
58
59
Getopt::Long::Configure('bundling');
60
GetOptions (
61
"H=s" => \$opt_H, "hostname=s" => \$opt_H,
62
"p=s" => \$opt_p, "port=s" => \$opt_p,
63
"m=s@" => \$opt_m, "module=s@" => \$opt_m );
64
65
unless (defined($opt_H)){
66
print "Usage: $PROGNAME -H <host> [-p <port>] [-m <module>[,<user>,<password>] [-m <module>[,<user>,<password>]...]]\n";
67
exit $ERRORS{'UNKNOWN'};
68
}
69
70
my $host = $opt_H;
71
my $port = defined($opt_p) ? $opt_p : 873;
72
my $verbose = 0; # Not implemented as argument yet
73
74
# Create an array for each -m arguments and store them in @modules
75
my @modules;
76
if (defined($opt_m)) {
77
for(@$opt_m) {
78
my @tmpmod = split(/,/);
79
my ($modname, $username) = @tmpmod;
80
my $pass = join(',', splice(@tmpmod, 2));
81
print STDERR "Adding module $modname\n" if ($verbose);
82
if ($pass) {
83
print STDERR "Module $modname using authentication ($username, $pass)\n" if ($verbose > 2);
84
push @modules, [ $modname, $username, $pass ];
85
} else {
86
push @modules, [ $modname ];
87
}
88
}
89
}
90
91
# Just in case of problems, let's not hang Nagios
92
$SIG{'ALRM'} = sub {
93
print "CRITICAL: Rsync timed out\n";
94
kill SIGKILL, $cpid if ($cpid);
95
exit $ERRORS{"CRITICAL"};
96
};
97
98
# Rsync arguments
99
my $source = "rsync://$host";
100
101
alarm($TIMEOUT);
102
103
# Get a list of modules to see if rsync is up
104
my $command = "/usr/bin/rsync --port=$port $source";
105
106
# Workaround to kill stale rsync processes
107
$cpid = open(RSYNC, "$command|") or report_error("Unable to execute rsync: $!");
108
my $result;
109
{
110
local $/;
111
$result = <RSYNC>;
112
}
113
close(RSYNC);
114
my $error_code = $?;
115
116
#Turn off alarm
117
alarm(0);
118
$cpid = 0;
119
120
my $realerr = $error_code >> 8;
121
report_error("Rsync command $command failed with error " . $realerr . ": " . (defined $RSYNCMSG{"$realerr"} ? $RSYNCMSG{"$realerr"} : "Unknown error")) if ($realerr != 0);
122
123
# If one or more -m, check if these modules exists first...
124
if (@modules) {
125
126
my @result = split(/\n/, $result);
127
128
foreach my $mod (@modules) {
129
my $match = 0;
130
for (@result) {
131
$match = 1 if (/^$$mod[0]\s/);
132
}
133
report_error("Module $$mod[0] not found") if ($match == 0);
134
}
135
} else { # else just return OK
136
print "OK: Rsync is up\n";
137
exit $ERRORS{'OK'};
138
}
139
140
# Check each -m aruments...
141
for my $arg (@modules) {
142
if (defined($$arg[1]) and defined($$arg[2])) {
143
$source = "rsync://$$arg[1]" . '@' . "$host/$$arg[0]";
144
$ENV{'RSYNC_PASSWORD'} = $$arg[2];
145
} else {
146
$source = "rsync://$host/$$arg[0]";
147
$ENV{'RSYNC_PASSWORD'} = '';
148
}
149
150
alarm($TIMEOUT);
151
152
# Better safe than sorry...
153
undef $error_code;
154
undef $result;
155
# Get a file listing of the root of the module
156
$command = "/usr/bin/rsync --port=$port $source";
157
158
# Workaround to kill stale rsync processes
159
$cpid = open(RSYNC, "$command|") or report_error("Unable to execute rsync: $!");
160
{
161
local $/;
162
$result = <RSYNC>;
163
}
164
close(RSYNC);
165
$error_code = $?;
166
167
#Turn off alarm
168
alarm(0);
169
$cpid = 0;
170
171
$realerr = $error_code >> 8;
172
report_error("Rsync command failed on module $$arg[0] with error " . $realerr . ": " . (defined $RSYNCMSG{$realerr} ? $RSYNCMSG{$realerr} : "Unknown error")) if ($realerr != 0);
173
}
174
175
if (@modules > 0) {
176
print "OK: Rsync is up with ", scalar(@modules), " module tested\n" if (@modules == 1);
177
print "OK: Rsync is up with ", scalar(@modules), " modules tested\n" if (@modules > 1);
178
exit $ERRORS{'OK'};
179
} else { # We hould never end up here :)
180
print "UNKNOWN: The unexpected occured (bug?)\n";
181
exit $ERRORS{'UNKNOWN'};
182
}
183
184
# Report error passed as one string, print rsync messages to STDERR
185
sub report_error {
186
my $report = shift;
187
print "CRITICAL: $report\n";
188
exit $ERRORS{'CRITICAL'};
189
}
190
191