diff options
-rwxr-xr-x | contrib/check_sybase | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/contrib/check_sybase b/contrib/check_sybase new file mode 100755 index 0000000..20b4a30 --- /dev/null +++ b/contrib/check_sybase | |||
@@ -0,0 +1,332 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | # check_sybase | ||
3 | # A nagios plugin that connects to a Sybase database and checks free space. | ||
4 | # | ||
5 | # Copyright 2004 Simon Bellwood, NetMan Network Management and IT Services GmbH | ||
6 | # Portions Copyright 2001 Michael Peppler. | ||
7 | # License: GPL | ||
8 | # | ||
9 | # Bugs and feedback to simon.bellwood@nospam.net-man.at | ||
10 | # Latest version available from: | ||
11 | # http://www.net-man.at/software/check_sybase-LATEST.zip | ||
12 | # | ||
13 | # Revision history: | ||
14 | # 0.1 01-OCT-2004 Initial version. | ||
15 | # 0.2 08-NOV-2004 Initial release. | ||
16 | my $VERSION = "0.2"; | ||
17 | |||
18 | use strict; | ||
19 | use DBI; | ||
20 | use Getopt::Long; | ||
21 | use lib "/usr/local/nagios/libexec"; | ||
22 | use utils qw(%ERRORS &print_revision &support &usage $TIMEOUT); | ||
23 | |||
24 | |||
25 | my $PROGNAME = "check_sybase"; | ||
26 | my $DEFAULT_CHECKTYPE = "FREESPACE"; | ||
27 | my $DEFAULT_WARNING = "25"; | ||
28 | my $DEFAULT_CRITICAL = "10"; | ||
29 | |||
30 | my ($user, $pass, $dbsvr, $dbname, $config, $checktype, $warn, $crit, $timeout, | ||
31 | $help, $version); | ||
32 | |||
33 | my $options_okay = GetOptions( | ||
34 | "U|user=s" => \$user, | ||
35 | "P|pass:s" => \$pass, # ":" means optional | ||
36 | "S|dbsvr=s" => \$dbsvr, | ||
37 | "D|dbname=s" => \$dbname, | ||
38 | "config=s" => \$config, | ||
39 | "checktype=s" => \$checktype, | ||
40 | "w|warning=i" => \$warn, | ||
41 | "c|critical=i" => \$crit, | ||
42 | "t|timeout=i" => \$timeout, | ||
43 | "h|help" => \$help, | ||
44 | "V|version" => \$version | ||
45 | ); | ||
46 | |||
47 | |||
48 | if (! $options_okay) # Bad option passed | ||
49 | { | ||
50 | &help; | ||
51 | &nunk("Bad command line option passed!"); | ||
52 | } | ||
53 | |||
54 | # Use defaults, if needed | ||
55 | $warn = $warn || $DEFAULT_WARNING; | ||
56 | $crit = $crit || $DEFAULT_CRITICAL; | ||
57 | $checktype = $checktype || $DEFAULT_CHECKTYPE; | ||
58 | $timeout = $timeout || $TIMEOUT; | ||
59 | |||
60 | if ($help) | ||
61 | { | ||
62 | &help; | ||
63 | &nok; | ||
64 | } | ||
65 | |||
66 | if ($version) | ||
67 | { | ||
68 | print_revision($PROGNAME,"\$Revision$VERSION \$"); | ||
69 | &nok; | ||
70 | } | ||
71 | |||
72 | if ($config) # Read any of "user", "pass", "dbsvr", "dbname" from config file | ||
73 | { | ||
74 | &read_config; | ||
75 | } | ||
76 | |||
77 | # Some more descriptive syntax checks | ||
78 | my $syntax_error; | ||
79 | $syntax_error .= "No dbsvr given! " unless $dbsvr; | ||
80 | $syntax_error .= "No dbname given! " unless $dbname; | ||
81 | $syntax_error .= "No user given! " unless $user; | ||
82 | $syntax_error .= "Bad checktype given!" | ||
83 | unless $checktype =~ m/^CONNECT|FREESPACE$/; | ||
84 | &nunk($syntax_error) if $syntax_error; | ||
85 | |||
86 | |||
87 | # Just in case of problems, let's not hang Nagios | ||
88 | $SIG{'ALRM'} = sub { | ||
89 | &nunk("Timeout: no response from dbsvr $dbsvr within $timeout seconds"); | ||
90 | }; | ||
91 | alarm($timeout); | ||
92 | |||
93 | |||
94 | # Decide on what we are checking | ||
95 | if ($checktype eq "CONNECT") | ||
96 | { | ||
97 | &connect; | ||
98 | } | ||
99 | elsif ($checktype eq "FREESPACE") | ||
100 | { | ||
101 | &check_space; | ||
102 | } | ||
103 | |||
104 | my $dbh; | ||
105 | my $is_connected; | ||
106 | sub connect | ||
107 | { | ||
108 | $dbh = DBI->connect("dbi:Sybase:server=$dbsvr;database=$dbname", | ||
109 | $user, $pass) | ||
110 | or &ncrit("Could not connect to '$dbname' on '$dbsvr'"); | ||
111 | |||
112 | # Report success for a check of type CONNECT | ||
113 | &nok("Connect okay") if $checktype ne "FREESPACE"; | ||
114 | } | ||
115 | |||
116 | sub disconnect | ||
117 | { | ||
118 | $dbh->disconnect if $is_connected; | ||
119 | $is_connected = 0; | ||
120 | } | ||
121 | |||
122 | sub check_space | ||
123 | { | ||
124 | &connect; | ||
125 | |||
126 | # Most of this sub based on Michael Peppler's check-space.pl | ||
127 | |||
128 | $dbh->{syb_do_proc_status} = 1; | ||
129 | |||
130 | my $dbinfo; | ||
131 | |||
132 | # First check space in the database | ||
133 | my $sth = $dbh->prepare("sp_spaceused") | ||
134 | or &nunk("Failed to call sp_spaceused on '$dbsvr'"); | ||
135 | $sth->execute | ||
136 | or &nunk("Failed to call sp_spaceused on '$dbsvr'"); | ||
137 | do { | ||
138 | while(my $d = $sth->fetch) | ||
139 | { | ||
140 | if($d->[0] =~ /$dbname/) | ||
141 | { | ||
142 | # Grab "database_size" | ||
143 | $d->[1] =~ s/[^\d.]//g; | ||
144 | $dbinfo->{size} = $d->[1]; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | foreach (@$d) | ||
149 | { | ||
150 | s/\D//g; | ||
151 | } | ||
152 | |||
153 | # Grab "reserved", "data", "index" | ||
154 | $dbinfo->{reserved} = $d->[0] / 1024; | ||
155 | $dbinfo->{data} = $d->[1] / 1024; | ||
156 | $dbinfo->{index} = $d->[2] / 1024; | ||
157 | } | ||
158 | } | ||
159 | } while($sth->{syb_more_results}); | ||
160 | |||
161 | # Get the actual device usage from sp_helpdb to get the free log space | ||
162 | $sth = $dbh->prepare("sp_helpdb $dbname") | ||
163 | or &nunk("Failed to call sp_helpdb $dbname on '$dbsvr'"); | ||
164 | $sth->execute | ||
165 | or &nunk("Failed to call sp_helpdb $dbname on '$dbsvr'"); | ||
166 | do { | ||
167 | while(my $d = $sth->fetch) | ||
168 | { | ||
169 | # Look for "usage" column with value "log only" | ||
170 | if($d->[2] && $d->[2] =~ /log only/) | ||
171 | { | ||
172 | # Grab "size", add it to our log size | ||
173 | $d->[1] =~ s/[^\d\.]//g; | ||
174 | $dbinfo->{log} += $d->[1]; | ||
175 | } | ||
176 | |||
177 | # Look for "device fragments" column with "log only" | ||
178 | # followed by a number. | ||
179 | if($d->[0] =~ /log only .* (\d+)/) | ||
180 | { | ||
181 | $dbinfo->{logfree} = $1 / 1024; | ||
182 | } | ||
183 | } | ||
184 | } while($sth->{syb_more_results}); | ||
185 | |||
186 | # Subtract the log size from the database size | ||
187 | $dbinfo->{size} -= $dbinfo->{log}; | ||
188 | |||
189 | # The "reserved" space is free for use by the table that freed it, so | ||
190 | # it is not truly free space. To be safe, our calculation ignores it. | ||
191 | my $free = ($dbinfo->{size} - $dbinfo->{reserved}) / $dbinfo->{size}; | ||
192 | $free = sprintf("%.2f", $free*100); | ||
193 | |||
194 | |||
195 | if ($free < $crit) | ||
196 | { | ||
197 | &ncrit("Free space is $free%! (critical threshold is $crit%)"); | ||
198 | } | ||
199 | |||
200 | if ($free < $warn) | ||
201 | { | ||
202 | &nwarn("Free space is $free%! (warning threshold is $warn%)"); | ||
203 | } | ||
204 | |||
205 | |||
206 | &nok("Free space within thresholds ($free% free)"); | ||
207 | } | ||
208 | |||
209 | sub read_config | ||
210 | { | ||
211 | open (CONFIG, "<$config") | ||
212 | or &nunk("Failed to open config file '$config': $!"); | ||
213 | while (<CONFIG>) | ||
214 | { | ||
215 | chomp; | ||
216 | next if m/^#/; # skip comments | ||
217 | next if m/^$/; # skip blanks | ||
218 | |||
219 | # Each case-insensitive argument can be followed by an optional | ||
220 | # colon, then must be followed by whitespace and the value. | ||
221 | # Options in the config file override those given on the | ||
222 | # command line, but don't rely on this! | ||
223 | |||
224 | if (m/USER:?\s+(\S+)/i) | ||
225 | { | ||
226 | $user = $1; | ||
227 | } | ||
228 | elsif (m/PASS:?\s+(\S+)/i) | ||
229 | { | ||
230 | $pass = $1; | ||
231 | } | ||
232 | elsif (m/DBSVR:?\s+(\S+)/i) | ||
233 | { | ||
234 | $dbsvr = $1; | ||
235 | } | ||
236 | elsif (m/DBNAME:?\s+(\S+)/i) | ||
237 | { | ||
238 | $dbname = $1; | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | &nunk("Invalid line $. in config file '$config'"); | ||
243 | } | ||
244 | } | ||
245 | close (CONFIG); | ||
246 | } | ||
247 | |||
248 | sub help | ||
249 | { | ||
250 | print <<_HELP_; | ||
251 | Usage: $PROGNAME OPTIONS | ||
252 | A nagios plugin that connects to a Sybase database and checks free space. | ||
253 | |||
254 | Mandatory arguments to long options are mandatory for short options too. | ||
255 | -U, --user Username to connect to database. | ||
256 | -P, --pass Password to connect to database. | ||
257 | -S, --dbsvr Database server (as in the interfaces file). | ||
258 | -D, --dbname Database name to check. | ||
259 | --config=FILE Config file (see SECURITY below) | ||
260 | --checktype=TYPE Type of check to run (see TYPEs below) | ||
261 | -w, --warning Warning threshold, in percent (default 25) | ||
262 | -c, --critical Critical threshold, in percent (default 10) | ||
263 | -t, --timeout Timeout value, in seconds (default 30) | ||
264 | -h, --help This help message | ||
265 | -V, --version Version information | ||
266 | |||
267 | Examples: | ||
268 | $PROGNAME -U sa -P secret -S bigbox -D orders | ||
269 | $PROGNAME --config=/secure/nagios-sybase.cfg --checktype=CONNECT | ||
270 | |||
271 | TYPEs | ||
272 | There are two types of checks you can run: | ||
273 | --checktype=CONNECT | ||
274 | Checks just the connection to the database. | ||
275 | --checktype=FREESPACE | ||
276 | (Default) Checks both the connection to the database and the free space. | ||
277 | |||
278 | SECURITY - Using a config file | ||
279 | Since a "ps ax" will reveal your database username and password, you can | ||
280 | instead specify them in a config file. Pass the config file with --config. | ||
281 | The format of the file is: | ||
282 | USER value | ||
283 | PASS value | ||
284 | You can also specify a DBSVR and DBNAME in the file. Comments (#) and blank | ||
285 | lines are ignored. Use whitespace to separate argument and value. | ||
286 | _HELP_ | ||
287 | |||
288 | } | ||
289 | |||
290 | |||
291 | |||
292 | # Some wrappers.. | ||
293 | |||
294 | # Returns code 0, OK | ||
295 | sub nok | ||
296 | { | ||
297 | my $msg = shift; | ||
298 | print "OK: $msg\n" if $msg; | ||
299 | |||
300 | &disconnect; | ||
301 | exit $ERRORS{OK}; | ||
302 | } | ||
303 | |||
304 | # Returns code 1, Warning | ||
305 | sub nwarn | ||
306 | { | ||
307 | my $msg = shift; | ||
308 | print "WARNING: $msg\n"; | ||
309 | |||
310 | &disconnect; | ||
311 | exit $ERRORS{WARNING}; | ||
312 | } | ||
313 | |||
314 | # Returns code 2, Critical | ||
315 | sub ncrit | ||
316 | { | ||
317 | my $msg = shift; | ||
318 | print "CRITICAL: $msg\n"; | ||
319 | |||
320 | &disconnect; | ||
321 | exit $ERRORS{CRITICAL}; | ||
322 | } | ||
323 | |||
324 | # Returns code 3, Unknown | ||
325 | sub nunk | ||
326 | { | ||
327 | my $msg = shift; | ||
328 | print "ERROR: $msg\n"; | ||
329 | |||
330 | &disconnect; | ||
331 | exit $ERRORS{UNKNOWN}; | ||
332 | } | ||