Code

check_tcp code cleanup from andreas plus fix to andreas' patch from sean
[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-2004";
20 const char *email = "nagiosplug-devel@lists.sourceforge.net";
22 #define SLAVERESULTSIZE 40
24 #include "common.h"
25 #include "utils.h"
26 #include "netutils.h"
28 #include <mysql/mysql.h>
29 #include <mysql/errmsg.h>
31 char *db_user = NULL;
32 char *db_host = NULL;
33 char *db_pass = NULL;
34 char *db = NULL;
35 unsigned int db_port = MYSQL_PORT;
36 int check_slave = 0;
38 int process_arguments (int, char **);
39 int validate_arguments (void);
40 void print_help (void);
41 void print_usage (void);
45 int
46 main (int argc, char **argv)
47 {
49         MYSQL mysql;
50         MYSQL_RES *res;
51         MYSQL_ROW row;
52         
53         /* should be status */
54         
55         char *result = NULL;
56         char slaveresult[SLAVERESULTSIZE];
58         setlocale (LC_ALL, "");
59         bindtextdomain (PACKAGE, LOCALEDIR);
60         textdomain (PACKAGE);
62         if (process_arguments (argc, argv) == ERROR)
63                 usage4 (_("Could not parse arguments"));
65         /* initialize mysql  */
66         mysql_init (&mysql);
68         /* establish a connection to the server and error checking */
69         if (!mysql_real_connect(&mysql,db_host,db_user,db_pass,db,db_port,NULL,0)) {
70                 if (mysql_errno (&mysql) == CR_UNKNOWN_HOST)
71                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
72                 else if (mysql_errno (&mysql) == CR_VERSION_ERROR)
73                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
74                 else if (mysql_errno (&mysql) == CR_OUT_OF_MEMORY)
75                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
76                 else if (mysql_errno (&mysql) == CR_IPSOCK_ERROR)
77                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
78                 else if (mysql_errno (&mysql) == CR_SOCKET_CREATE_ERROR)
79                         die (STATE_WARNING, "%s\n", mysql_error (&mysql));
80                 else
81                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
82         }
84         /* get the server stats */
85         result = strdup (mysql_stat (&mysql));
87         /* error checking once more */
88         if (mysql_error (&mysql)) {
89                 if (mysql_errno (&mysql) == CR_SERVER_GONE_ERROR)
90                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
91                 else if (mysql_errno (&mysql) == CR_SERVER_LOST)
92                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
93                 else if (mysql_errno (&mysql) == CR_UNKNOWN_ERROR)
94                         die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
95         }
97         if(check_slave) {
98                 /* check the slave status */
99                 if (mysql_query (&mysql, "show slave status") != 0) {
100                         mysql_close (&mysql);
101                         die (STATE_CRITICAL, _("slave query error: %s\n"), mysql_error (&mysql));
102                 }
104                 /* store the result */
105                 if ( (res = mysql_store_result (&mysql)) == NULL) {
106                         mysql_close (&mysql);
107                         die (STATE_CRITICAL, _("slave store_result error: %s\n"), mysql_error (&mysql));
108                 }
110                 /* fetch the first row */
111                 if ( (row = mysql_fetch_row (res)) == NULL) {
112                         mysql_free_result (res);
113                         mysql_close (&mysql);
114                         die (STATE_CRITICAL, _("slave fetch row error: %s\n"), mysql_error (&mysql));
115                 }
117                 if (mysql_field_count (&mysql) == 12) {
118                         /* mysql 3.23.x */
119                         snprintf (slaveresult, SLAVERESULTSIZE, _("Slave running: %s"), row[6]);
120                         if (strcmp (row[6], "Yes") != 0) {
121                                 mysql_free_result (res);
122                                 mysql_close (&mysql);
123                                 die (STATE_CRITICAL, "%s\n", slaveresult);
124                         }
126                 } else {
127                         /* mysql 4.x.x */
128                         int slave_io_field = -1 , slave_sql_field = -1, i, num_fields;
129                         MYSQL_FIELD* fields;
131                         num_fields = mysql_num_fields(res);
132                         fields = mysql_fetch_fields(res);
133                         for(i = 0; i < num_fields; i++)
134                         {
135                                 if (0 == strcmp(fields[i].name, "Slave_IO_Running"))
136                                 {
137                                         slave_io_field = i;
138                                         continue;
139                                 }
140                                 if (0 == strcmp(fields[i].name, "Slave_SQL_Running"))
141                                 {
142                                         slave_sql_field = i;
143                                         continue;
144                                 }
145                         }
146                         if ((slave_io_field < 0) || (slave_sql_field < 0) || (num_fields == 0))
147                         {
148                                 mysql_free_result (res);
149                                 mysql_close (&mysql);
150                                 die (STATE_CRITICAL, "Slave status unavailable\n");
151                         }
152                          
153                         snprintf (slaveresult, SLAVERESULTSIZE, "Slave IO: %s Slave SQL: %s", row[slave_io_field], row[slave_sql_field]);
154                         if (strcmp (row[slave_io_field], "Yes") != 0 || strcmp (row[slave_sql_field], "Yes") != 0) {
155                                 mysql_free_result (res);
156                                 mysql_close (&mysql);
157                                 die (STATE_CRITICAL, "%s\n", slaveresult);
158                         }
159                 }
161                 /* free the result */
162                 mysql_free_result (res);
163         }
165         /* close the connection */
166         mysql_close (&mysql);
168         /* print out the result of stats */
169         if (check_slave) {
170                 printf ("%s %s\n", result, slaveresult);
171         } else {
172                 printf ("%s\n", result);
173         }
175         return STATE_OK;
179 /* process command-line arguments */
180 int
181 process_arguments (int argc, char **argv)
183         int c;
185         int option = 0;
186         static struct option longopts[] = {
187                 {"hostname", required_argument, 0, 'H'},
188                 {"database", required_argument, 0, 'd'},
189                 {"username", required_argument, 0, 'u'},
190                 {"password", required_argument, 0, 'p'},
191                 {"port", required_argument, 0, 'P'},
192                 {"check-slave", no_argument, 0, 'S'},
193                 {"verbose", no_argument, 0, 'v'},
194                 {"version", no_argument, 0, 'V'},
195                 {"help", no_argument, 0, 'h'},
196                 {0, 0, 0, 0}
197         };
199         if (argc < 1)
200                 return ERROR;
202         while (1) {
203                 c = getopt_long (argc, argv, "hVSP:p:u:d:H:", longopts, &option);
205                 if (c == -1 || c == EOF)
206                         break;
208                 switch (c) {
209                 case 'H':                                                                       /* hostname */
210                         if (is_host (optarg)) {
211                                 db_host = optarg;
212                         }
213                         else {
214                                 usage2 (_("Invalid hostname/address"), optarg);
215                         }
216                         break;
217                 case 'd':                                                                       /* hostname */
218                         db = optarg;
219                         break;
220                 case 'u':                                                                       /* username */
221                         db_user = optarg;
222                         break;
223                 case 'p':                                                                       /* authentication information: password */
224                         db_pass = optarg;
225                         break;
226                 case 'P':                                                                       /* critical time threshold */
227                         db_port = atoi (optarg);
228                         break;
229                 case 'S':
230                         check_slave = 1;                                                        /* check-slave */
231                         break;
232                 case 'V':                                                                       /* version */
233                         print_revision (progname, revision);
234                         exit (STATE_OK);
235                 case 'h':                                                                       /* help */
236                         print_help ();
237                         exit (STATE_OK);
238                 case '?':                                                                       /* help */
239                         usage2 (_("Unknown argument"), optarg);
240                 }
241         }
243         c = optind;
245         while ( argc > c ) {
247                 if (strlen(db_host) == 0)
248                         if (is_host (argv[c])) {
249                                 db_host = argv[c++];
250                         }
251                         else {
252                                 usage2 (_("Invalid hostname/address"), optarg);
253                         }
254                 else if (strlen(db_user) == 0)
255                         db_user = argv[c++];
256                 else if (strlen(db_pass) == 0)
257                         db_pass = argv[c++];
258                 else if (strlen(db) == 0)
259                         db = argv[c++];
260                 else if (is_intnonneg (argv[c]))
261                         db_port = atoi (argv[c++]);
262                 else
263                         break;
264         }
266         return validate_arguments ();
270 int
271 validate_arguments (void)
273         if (db_user == NULL)
274                 db_user = strdup("");
276         if (db_host == NULL)
277                 db_host = strdup("");
279         if (db_pass == NULL)
280                 db_pass == strdup("");
282         if (db == NULL)
283                 db = strdup("");
285         return OK;
289 void
290 print_help (void)
292         char *myport;
293         asprintf (&myport, "%d", MYSQL_PORT);
295         print_revision (progname, revision);
297         printf (_(COPYRIGHT), copyright, email);
299         printf (_("This program tests connections to a mysql server\n"));
301         print_usage ();
303         printf (_(UT_HELP_VRSN));
305         printf (_(UT_HOST_PORT), 'P', myport);
307         printf (_("\
308  -d, --database=STRING\n\
309    Check database with indicated name\n\
310  -u, --username=STRING\n\
311    Connect using the indicated username\n\
312  -p, --password=STRING\n\
313    Use the indicated password to authenticate the connection\n\
314    ==> IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!! <==\n\
315    Your clear-text password will be visible as a process table entry\n\
316  -S, --check-slave\n\
317    Check if the slave thread is running properly.\n"));
319         printf (_("\n\
320 There are no required arguments. By default, the local database with\n\
321 a server listening on MySQL standard port %d will be checked\n"), MYSQL_PORT);
323         printf (_(UT_SUPPORT));
327 void
328 print_usage (void)
330         printf ("\
331 Usage: %s [-d database] [-H host] [-P port] [-u user] [-p password] [-S]\n",
332                 progname);