Code

Move new util_* functions to lib/
[nagiosplug.git] / plugins / check_mysql.c
1 /******************************************************************************
2 *
3 * CHECK_MYSQL.C
4 *
5 * Program: Mysql plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
8 *  portions (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
9 *
10 * $Id$
11 *
12 * Description:
13 *
14 * This plugin is for testing a mysql server.
15 ******************************************************************************/
17 const char *progname = "check_mysql";
18 const char *revision = "$Revision$";
19 const char *copyright = "1999-2006";
20 const char *email = "nagiosplug-devel@lists.sourceforge.net";
22 #define SLAVERESULTSIZE 70
24 #include "common.h"
25 #include "utils.h"
26 #include "utils_base.h"
27 #include "netutils.h"
29 #include <mysql.h>
30 #include <errmsg.h>
32 char *db_user = NULL;
33 char *db_host = NULL;
34 char *db_pass = NULL;
35 char *db = NULL;
36 unsigned int db_port = MYSQL_PORT;
37 int check_slave = 0, warn_sec = 0, crit_sec = 0;
38 int verbose = 0;
40 thresholds *my_threshold = NULL;
42 int process_arguments (int, char **);
43 int validate_arguments (void);
44 void print_help (void);
45 void print_usage (void);
47 int
48 main (int argc, char **argv)
49 {
51         MYSQL mysql;
52         MYSQL_RES *res;
53         MYSQL_ROW row;
54         
55         /* should be status */
56         
57         char *result = NULL;
58         char *error = NULL;
59         char slaveresult[SLAVERESULTSIZE];
61         setlocale (LC_ALL, "");
62         bindtextdomain (PACKAGE, LOCALEDIR);
63         textdomain (PACKAGE);
65         if (process_arguments (argc, argv) == ERROR)
66                 usage4 (_("Could not parse arguments"));
68         /* initialize mysql  */
69         mysql_init (&mysql);
71         mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"client");
73         /* establish a connection to the server and error checking */
74         if (!mysql_real_connect(&mysql,db_host,db_user,db_pass,db,db_port,NULL,0)) {
75                 if (mysql_errno (&mysql) == CR_UNKNOWN_HOST)
76                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
77                 else if (mysql_errno (&mysql) == CR_VERSION_ERROR)
78                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
79                 else if (mysql_errno (&mysql) == CR_OUT_OF_MEMORY)
80                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
81                 else if (mysql_errno (&mysql) == CR_IPSOCK_ERROR)
82                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
83                 else if (mysql_errno (&mysql) == CR_SOCKET_CREATE_ERROR)
84                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
85                 else
86                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
87         }
89         /* get the server stats */
90         result = strdup (mysql_stat (&mysql));
92         /* error checking once more */
93         if (mysql_error (&mysql)) {
94                 if (mysql_errno (&mysql) == CR_SERVER_GONE_ERROR)
95                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
96                 else if (mysql_errno (&mysql) == CR_SERVER_LOST)
97                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
98                 else if (mysql_errno (&mysql) == CR_UNKNOWN_ERROR)
99                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
100         }
102         if(check_slave) {
103                 /* check the slave status */
104                 if (mysql_query (&mysql, "show slave status") != 0) {
105                         error = strdup(mysql_error(&mysql));
106                         mysql_close (&mysql);
107                         die (STATE_CRITICAL, _("slave query error: %s\n"), error);
108                 }
110                 /* store the result */
111                 if ( (res = mysql_store_result (&mysql)) == NULL) {
112                         error = strdup(mysql_error(&mysql));
113                         mysql_close (&mysql);
114                         die (STATE_CRITICAL, _("slave store_result error: %s\n"), error);
115                 }
117                 /* Check there is some data */
118                 if (mysql_num_rows(res) == 0) {
119                         mysql_close(&mysql);
120                         die (STATE_WARNING, "%s\n", _("No slaves defined"));
121                 }
123                 /* fetch the first row */
124                 if ( (row = mysql_fetch_row (res)) == NULL) {
125                         error = strdup(mysql_error(&mysql));
126                         mysql_free_result (res);
127                         mysql_close (&mysql);
128                         die (STATE_CRITICAL, _("slave fetch row error: %s\n"), error);
129                 }
131                 if (mysql_field_count (&mysql) == 12) {
132                         /* mysql 3.23.x */
133                         snprintf (slaveresult, SLAVERESULTSIZE, _("Slave running: %s"), row[6]);
134                         if (strcmp (row[6], "Yes") != 0) {
135                                 mysql_free_result (res);
136                                 mysql_close (&mysql);
137                                 die (STATE_CRITICAL, "%s\n", slaveresult);
138                         }
140                 } else {
141                         /* mysql 4.x.x */
142                         int slave_io_field = -1 , slave_sql_field = -1, seconds_behind_field = -1, i, num_fields;
143                         MYSQL_FIELD* fields;
145                         num_fields = mysql_num_fields(res);
146                         fields = mysql_fetch_fields(res);
147                         for(i = 0; i < num_fields; i++) {
148                                 if (strcmp(fields[i].name, "Slave_IO_Running") == 0) {
149                                         slave_io_field = i;
150                                         continue;
151                                 }
152                                 if (strcmp(fields[i].name, "Slave_SQL_Running") == 0) {
153                                         slave_sql_field = i;
154                                         continue;
155                                 }
156                                 if (strcmp(fields[i].name, "Seconds_Behind_Master") == 0) {
157                                         seconds_behind_field = i;
158                                         continue;
159                                 }
160                         }
161                         if ((slave_io_field < 0) || (slave_sql_field < 0) || (num_fields == 0)) {
162                                 mysql_free_result (res);
163                                 mysql_close (&mysql);
164                                 die (STATE_CRITICAL, "Slave status unavailable\n");
165                         }
166                         
167                         snprintf (slaveresult, SLAVERESULTSIZE, "Slave IO: %s Slave SQL: %s Seconds Behind Master: %s", row[slave_io_field], row[slave_sql_field], row[seconds_behind_field]);
168                         if (strcmp (row[slave_io_field], "Yes") != 0 || strcmp (row[slave_sql_field], "Yes") != 0) {
169                                 mysql_free_result (res);
170                                 mysql_close (&mysql);
171                                 die (STATE_CRITICAL, "%s\n", slaveresult);
172                         }
174                         if (verbose >=3) {
175                                 if (seconds_behind_field == -1) {
176                                         printf("seconds_behind_field not found\n");
177                                 } else {
178                                         printf ("seconds_behind_field(index %d)=%s\n", seconds_behind_field, row[seconds_behind_field]);
179                                 }
180                         }
182                         if ((seconds_behind_field != -1) && (strcmp (row[seconds_behind_field], "NULL") != 0)) {
183                                 double value = atof(row[seconds_behind_field]);
184                                 int status;
186                                 status = get_status(value, my_threshold);
188                                 if (status == STATE_WARNING) {
189                                         printf("SLOW_SLAVE %s: %s\n", _("WARNING"), slaveresult);
190                                         exit(STATE_WARNING);
191                                 } else if (status == STATE_CRITICAL) {
192                                         printf("SLOW_SLAVE %s: %s\n", _("CRITICAL"), slaveresult);
193                                         exit(STATE_CRITICAL);
194                                 }
195                         }
196                 }
198                 /* free the result */
199                 mysql_free_result (res);
200         }
202         /* close the connection */
203         mysql_close (&mysql);
205         /* print out the result of stats */
206         if (check_slave) {
207                 printf ("%s %s\n", result, slaveresult);
208         } else {
209                 printf ("%s\n", result);
210         }
212         return STATE_OK;
216 /* process command-line arguments */
217 int
218 process_arguments (int argc, char **argv)
220         int c;
221         char *warning = NULL;
222         char *critical = NULL;
224         int option = 0;
225         static struct option longopts[] = {
226                 {"hostname", required_argument, 0, 'H'},
227                 {"database", required_argument, 0, 'd'},
228                 {"username", required_argument, 0, 'u'},
229                 {"password", required_argument, 0, 'p'},
230                 {"port", required_argument, 0, 'P'},
231                 {"critical", required_argument, 0, 'c'},
232                 {"warning", required_argument, 0, 'w'},
233                 {"check-slave", no_argument, 0, 'S'},
234                 {"verbose", no_argument, 0, 'v'},
235                 {"version", no_argument, 0, 'V'},
236                 {"help", no_argument, 0, 'h'},
237                 {0, 0, 0, 0}
238         };
240         if (argc < 1)
241                 return ERROR;
243         while (1) {
244                 c = getopt_long (argc, argv, "hvVSP:p:u:d:H:c:w:", longopts, &option);
246                 if (c == -1 || c == EOF)
247                         break;
249                 switch (c) {
250                 case 'H':                                                                       /* hostname */
251                         if (is_host (optarg)) {
252                                 db_host = optarg;
253                         }
254                         else {
255                                 usage2 (_("Invalid hostname/address"), optarg);
256                         }
257                         break;
258                 case 'd':                                                                       /* hostname */
259                         db = optarg;
260                         break;
261                 case 'u':                                                                       /* username */
262                         db_user = optarg;
263                         break;
264                 case 'p':                                                                       /* authentication information: password */
265                         db_pass = optarg;
266                         break;
267                 case 'P':                                                                       /* critical time threshold */
268                         db_port = atoi (optarg);
269                         break;
270                 case 'S':
271                         check_slave = 1;                                                        /* check-slave */
272                         break;
273                 case 'w':
274                         warning = optarg;
275                         break;
276                 case 'c':
277                         critical = optarg;
278                         break;
279                 case 'V':                                                                       /* version */
280                         print_revision (progname, revision);
281                         exit (STATE_OK);
282                 case 'h':                                                                       /* help */
283                         print_help ();
284                         exit (STATE_OK);
285                 case 'v':
286                         verbose++;
287                         break;
288                 case '?':                                                                       /* help */
289                         usage2 (_("Unknown argument"), optarg);
290                 }
291         }
293         c = optind;
295         set_thresholds(&my_threshold, warning, critical);
297         while ( argc > c ) {
299                 if (strlen(db_host) == 0)
300                         if (is_host (argv[c])) {
301                                 db_host = argv[c++];
302                         }
303                         else {
304                                 usage2 (_("Invalid hostname/address"), optarg);
305                         }
306                 else if (strlen(db_user) == 0)
307                         db_user = argv[c++];
308                 else if (strlen(db_pass) == 0)
309                         db_pass = argv[c++];
310                 else if (strlen(db) == 0)
311                         db = argv[c++];
312                 else if (is_intnonneg (argv[c]))
313                         db_port = atoi (argv[c++]);
314                 else
315                         break;
316         }
318         return validate_arguments ();
322 int
323 validate_arguments (void)
325         if (db_user == NULL)
326                 db_user = strdup("");
328         if (db_host == NULL)
329                 db_host = strdup("");
331         if (db_pass == NULL)
332                 db_pass == strdup("");
334         if (db == NULL)
335                 db = strdup("");
337         return OK;
341 void
342 print_help (void)
344         char *myport;
345         asprintf (&myport, "%d", MYSQL_PORT);
347         print_revision (progname, revision);
349         printf (_(COPYRIGHT), copyright, email);
351         printf ("%s\n", _("This program tests connections to a mysql server"));
353   printf ("\n\n");
354   
355         print_usage ();
357         printf (_(UT_HELP_VRSN));
359         printf (_(UT_HOST_PORT), 'P', myport);
361         printf (" %s\n", "-d, --database=STRING");
362   printf ("    %s\n", _("Check database with indicated name"));
363   printf (" %s\n", "-u, --username=STRING");
364   printf ("    %s\n", _("Connect using the indicated username"));
365   printf (" %s\n", "-p, --password=STRING");
366   printf ("    %s\n", _("Use the indicated password to authenticate the connection"));
367   printf ("    %s\n", _("==> IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!! <=="));
368   printf ("    %s\n", _("Your clear-text password will be visible as a process table entry"));
369   printf (" %s\n", "-S, --check-slave");
370   printf ("    %s\n", _("Check if the slave thread is running properly."));
371   printf (" %s\n", "-w, --warning");
372   printf ("    %s\n", _("Exit with WARNING status if slave server is more then INTEGER seconds behind master"));
373   printf (" %s\n", "-c, --critical");
374   printf ("    %s\n", _("Exit with CRITICAL status if slave server is more then INTEGER seconds behind master"));
375   printf (" %s\n", _("There are no required arguments. By default, the local database with"));
376   printf (_("a server listening on MySQL standard port %d will be checked\n"), MYSQL_PORT);
378         printf (_(UT_SUPPORT));
382 void
383 print_usage (void)
385         printf (_("Usage:"));
386   printf ("%s [-d database] [-H host] [-P port] [-u user] [-p password] [-S]\n",progname);