check_sybase 7.5 KB

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