Back to index

nagios-plugins  1.4.16
check_mysql.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * 
00003 * Nagios check_mysql plugin
00004 * 
00005 * License: GPL
00006 * Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
00007 * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
00008 * Copyright (c) 1999-2009 Nagios Plugins Development Team
00009 * 
00010 * Description:
00011 * 
00012 * This file contains the check_mysql plugin
00013 * 
00014 * This program tests connections to a mysql server
00015 * 
00016 * 
00017 * This program is free software: you can redistribute it and/or modify
00018 * it under the terms of the GNU General Public License as published by
00019 * the Free Software Foundation, either version 3 of the License, or
00020 * (at your option) any later version.
00021 * 
00022 * This program is distributed in the hope that it will be useful,
00023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 * GNU General Public License for more details.
00026 * 
00027 * You should have received a copy of the GNU General Public License
00028 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00029 * 
00030 * 
00031 *****************************************************************************/
00032 
00033 const char *progname = "check_mysql";
00034 const char *copyright = "1999-2007";
00035 const char *email = "nagiosplug-devel@lists.sourceforge.net";
00036 
00037 #define SLAVERESULTSIZE 70
00038 
00039 #include "common.h"
00040 #include "utils.h"
00041 #include "utils_base.h"
00042 #include "netutils.h"
00043 
00044 #include <mysql.h>
00045 #include <errmsg.h>
00046 
00047 char *db_user = NULL;
00048 char *db_host = NULL;
00049 char *db_socket = NULL;
00050 char *db_pass = NULL;
00051 char *db = NULL;
00052 unsigned int db_port = MYSQL_PORT;
00053 int check_slave = 0, warn_sec = 0, crit_sec = 0;
00054 int verbose = 0;
00055 
00056 thresholds *my_threshold = NULL;
00057 
00058 int process_arguments (int, char **);
00059 int validate_arguments (void);
00060 void print_help (void);
00061 void print_usage (void);
00062 
00063 int
00064 main (int argc, char **argv)
00065 {
00066 
00067        MYSQL mysql;
00068        MYSQL_RES *res;
00069        MYSQL_ROW row;
00070 
00071        /* should be status */
00072 
00073        char *result = NULL;
00074        char *error = NULL;
00075        char slaveresult[SLAVERESULTSIZE];
00076 
00077        setlocale (LC_ALL, "");
00078        bindtextdomain (PACKAGE, LOCALEDIR);
00079        textdomain (PACKAGE);
00080 
00081        /* Parse extra opts if any */
00082        argv=np_extra_opts (&argc, argv, progname);
00083 
00084        if (process_arguments (argc, argv) == ERROR)
00085               usage4 (_("Could not parse arguments"));
00086 
00087        /* initialize mysql  */
00088        mysql_init (&mysql);
00089 
00090        mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"client");
00091 
00092        /* establish a connection to the server and error checking */
00093        if (!mysql_real_connect(&mysql,db_host,db_user,db_pass,db,db_port,db_socket,0)) {
00094               if (mysql_errno (&mysql) == CR_UNKNOWN_HOST)
00095                      die (STATE_WARNING, "%s\n", mysql_error (&mysql));
00096               else if (mysql_errno (&mysql) == CR_VERSION_ERROR)
00097                      die (STATE_WARNING, "%s\n", mysql_error (&mysql));
00098               else if (mysql_errno (&mysql) == CR_OUT_OF_MEMORY)
00099                      die (STATE_WARNING, "%s\n", mysql_error (&mysql));
00100               else if (mysql_errno (&mysql) == CR_IPSOCK_ERROR)
00101                      die (STATE_WARNING, "%s\n", mysql_error (&mysql));
00102               else if (mysql_errno (&mysql) == CR_SOCKET_CREATE_ERROR)
00103                      die (STATE_WARNING, "%s\n", mysql_error (&mysql));
00104               else
00105                      die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
00106        }
00107 
00108        /* get the server stats */
00109        result = strdup (mysql_stat (&mysql));
00110 
00111        /* error checking once more */
00112        if (mysql_error (&mysql)) {
00113               if (mysql_errno (&mysql) == CR_SERVER_GONE_ERROR)
00114                      die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
00115               else if (mysql_errno (&mysql) == CR_SERVER_LOST)
00116                      die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
00117               else if (mysql_errno (&mysql) == CR_UNKNOWN_ERROR)
00118                      die (STATE_CRITICAL, "%s\n", mysql_error (&mysql));
00119        }
00120 
00121        if(check_slave) {
00122               /* check the slave status */
00123               if (mysql_query (&mysql, "show slave status") != 0) {
00124                      error = strdup(mysql_error(&mysql));
00125                      mysql_close (&mysql);
00126                      die (STATE_CRITICAL, _("slave query error: %s\n"), error);
00127               }
00128 
00129               /* store the result */
00130               if ( (res = mysql_store_result (&mysql)) == NULL) {
00131                      error = strdup(mysql_error(&mysql));
00132                      mysql_close (&mysql);
00133                      die (STATE_CRITICAL, _("slave store_result error: %s\n"), error);
00134               }
00135 
00136               /* Check there is some data */
00137               if (mysql_num_rows(res) == 0) {
00138                      mysql_close(&mysql);
00139                      die (STATE_WARNING, "%s\n", _("No slaves defined"));
00140               }
00141 
00142               /* fetch the first row */
00143               if ( (row = mysql_fetch_row (res)) == NULL) {
00144                      error = strdup(mysql_error(&mysql));
00145                      mysql_free_result (res);
00146                      mysql_close (&mysql);
00147                      die (STATE_CRITICAL, _("slave fetch row error: %s\n"), error);
00148               }
00149 
00150               if (mysql_field_count (&mysql) == 12) {
00151                      /* mysql 3.23.x */
00152                      snprintf (slaveresult, SLAVERESULTSIZE, _("Slave running: %s"), row[6]);
00153                      if (strcmp (row[6], "Yes") != 0) {
00154                             mysql_free_result (res);
00155                             mysql_close (&mysql);
00156                             die (STATE_CRITICAL, "%s\n", slaveresult);
00157                      }
00158 
00159               } else {
00160                      /* mysql 4.x.x */
00161                      int slave_io_field = -1 , slave_sql_field = -1, seconds_behind_field = -1, i, num_fields;
00162                      MYSQL_FIELD* fields;
00163 
00164                      num_fields = mysql_num_fields(res);
00165                      fields = mysql_fetch_fields(res);
00166                      for(i = 0; i < num_fields; i++) {
00167                             if (strcmp(fields[i].name, "Slave_IO_Running") == 0) {
00168                                    slave_io_field = i;
00169                                    continue;
00170                             }
00171                             if (strcmp(fields[i].name, "Slave_SQL_Running") == 0) {
00172                                    slave_sql_field = i;
00173                                    continue;
00174                             }
00175                             if (strcmp(fields[i].name, "Seconds_Behind_Master") == 0) {
00176                                    seconds_behind_field = i;
00177                                    continue;
00178                             }
00179                      }
00180 
00181                      if ((slave_io_field < 0) || (slave_sql_field < 0) || (num_fields == 0)) {
00182                             mysql_free_result (res);
00183                             mysql_close (&mysql);
00184                             die (STATE_CRITICAL, "Slave status unavailable\n");
00185                      }
00186 
00187                      snprintf (slaveresult, SLAVERESULTSIZE, "Slave IO: %s Slave SQL: %s Seconds Behind Master: %s", row[slave_io_field], row[slave_sql_field], seconds_behind_field!=-1?row[seconds_behind_field]:"Unknown");
00188                      if (strcmp (row[slave_io_field], "Yes") != 0 || strcmp (row[slave_sql_field], "Yes") != 0) {
00189                             mysql_free_result (res);
00190                             mysql_close (&mysql);
00191                             die (STATE_CRITICAL, "%s\n", slaveresult);
00192                      }
00193 
00194                      if (verbose >=3) {
00195                             if (seconds_behind_field == -1) {
00196                                    printf("seconds_behind_field not found\n");
00197                             } else {
00198                                    printf ("seconds_behind_field(index %d)=%s\n", seconds_behind_field, row[seconds_behind_field]);
00199                             }
00200                      }
00201 
00202                      if ((seconds_behind_field != -1) && (strcmp (row[seconds_behind_field], "NULL") != 0)) {
00203                             double value = atof(row[seconds_behind_field]);
00204                             int status;
00205 
00206                             status = get_status(value, my_threshold);
00207 
00208                             if (status == STATE_WARNING) {
00209                                    printf("SLOW_SLAVE %s: %s\n", _("WARNING"), slaveresult);
00210                                    exit(STATE_WARNING);
00211                             } else if (status == STATE_CRITICAL) {
00212                                    printf("SLOW_SLAVE %s: %s\n", _("CRITICAL"), slaveresult);
00213                                    exit(STATE_CRITICAL);
00214                             }
00215                      }
00216               }
00217 
00218               /* free the result */
00219               mysql_free_result (res);
00220        }
00221 
00222        /* close the connection */
00223        mysql_close (&mysql);
00224 
00225        /* print out the result of stats */
00226        if (check_slave) {
00227               printf ("%s %s\n", result, slaveresult);
00228        } else {
00229               printf ("%s\n", result);
00230        }
00231 
00232        return STATE_OK;
00233 }
00234 
00235 
00236 /* process command-line arguments */
00237 int
00238 process_arguments (int argc, char **argv)
00239 {
00240        int c;
00241        char *warning = NULL;
00242        char *critical = NULL;
00243 
00244        int option = 0;
00245        static struct option longopts[] = {
00246               {"hostname", required_argument, 0, 'H'},
00247               {"socket", required_argument, 0, 's'},
00248               {"database", required_argument, 0, 'd'},
00249               {"username", required_argument, 0, 'u'},
00250               {"password", required_argument, 0, 'p'},
00251               {"port", required_argument, 0, 'P'},
00252               {"critical", required_argument, 0, 'c'},
00253               {"warning", required_argument, 0, 'w'},
00254               {"check-slave", no_argument, 0, 'S'},
00255               {"verbose", no_argument, 0, 'v'},
00256               {"version", no_argument, 0, 'V'},
00257               {"help", no_argument, 0, 'h'},
00258               {0, 0, 0, 0}
00259        };
00260 
00261        if (argc < 1)
00262               return ERROR;
00263 
00264        while (1) {
00265               c = getopt_long (argc, argv, "hvVSP:p:u:d:H:s:c:w:", longopts, &option);
00266 
00267               if (c == -1 || c == EOF)
00268                      break;
00269 
00270               switch (c) {
00271               case 'H':                                                             /* hostname */
00272                      if (is_host (optarg)) {
00273                             db_host = optarg;
00274                      }
00275                      else {
00276                             usage2 (_("Invalid hostname/address"), optarg);
00277                      }
00278                      break;
00279               case 's':                                                             /* socket */
00280                      db_socket = optarg;
00281                      break;
00282               case 'd':                                                             /* database */
00283                      db = optarg;
00284                      break;
00285               case 'u':                                                             /* username */
00286                      db_user = optarg;
00287                      break;
00288               case 'p':                                                             /* authentication information: password */
00289                      db_pass = strdup(optarg);
00290 
00291                      /* Delete the password from process list */
00292                      while (*optarg != '\0') {
00293                             *optarg = 'X';
00294                             optarg++;
00295                      }
00296                      break;
00297               case 'P':                                                             /* critical time threshold */
00298                      db_port = atoi (optarg);
00299                      break;
00300               case 'S':
00301                      check_slave = 1;                                               /* check-slave */
00302                      break;
00303               case 'w':
00304                      warning = optarg;
00305                      break;
00306               case 'c':
00307                      critical = optarg;
00308                      break;
00309               case 'V':                                                             /* version */
00310                      print_revision (progname, NP_VERSION);
00311                      exit (STATE_OK);
00312               case 'h':                                                             /* help */
00313                      print_help ();
00314                      exit (STATE_OK);
00315               case 'v':
00316                      verbose++;
00317                      break;
00318               case '?':                                                             /* help */
00319                      usage5 ();
00320               }
00321        }
00322 
00323        c = optind;
00324 
00325        set_thresholds(&my_threshold, warning, critical);
00326 
00327        while ( argc > c ) {
00328 
00329               if (db_host == NULL)
00330                      if (is_host (argv[c])) {
00331                             db_host = argv[c++];
00332                      }
00333                      else {
00334                             usage2 (_("Invalid hostname/address"), argv[c]);
00335                      }
00336               else if (db_user == NULL)
00337                      db_user = argv[c++];
00338               else if (db_pass == NULL)
00339                      db_pass = argv[c++];
00340               else if (db == NULL)
00341                      db = argv[c++];
00342               else if (is_intnonneg (argv[c]))
00343                      db_port = atoi (argv[c++]);
00344               else
00345                      break;
00346        }
00347 
00348        return validate_arguments ();
00349 }
00350 
00351 
00352 int
00353 validate_arguments (void)
00354 {
00355        if (db_user == NULL)
00356               db_user = strdup("");
00357 
00358        if (db_host == NULL)
00359               db_host = strdup("");
00360 
00361        if (db == NULL)
00362               db = strdup("");
00363 
00364        return OK;
00365 }
00366 
00367 
00368 void
00369 print_help (void)
00370 {
00371        char *myport;
00372        asprintf (&myport, "%d", MYSQL_PORT);
00373 
00374        print_revision (progname, NP_VERSION);
00375 
00376        printf (_(COPYRIGHT), copyright, email);
00377 
00378        printf ("%s\n", _("This program tests connections to a MySQL server"));
00379 
00380   printf ("\n\n");
00381 
00382        print_usage ();
00383 
00384   printf (UT_HELP_VRSN);
00385        printf (UT_EXTRA_OPTS);
00386 
00387   printf (UT_HOST_PORT, 'P', myport);
00388   printf (" %s\n", "-s, --socket=STRING");
00389   printf ("    %s\n", _("Use the specified socket (has no effect if -H is used)"));
00390 
00391   printf (" %s\n", "-d, --database=STRING");
00392   printf ("    %s\n", _("Check database with indicated name"));
00393   printf (" %s\n", "-u, --username=STRING");
00394   printf ("    %s\n", _("Connect using the indicated username"));
00395   printf (" %s\n", "-p, --password=STRING");
00396   printf ("    %s\n", _("Use the indicated password to authenticate the connection"));
00397   printf ("    ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!"));
00398   printf ("    %s\n", _("Your clear-text password could be visible as a process table entry"));
00399   printf (" %s\n", "-S, --check-slave");
00400   printf ("    %s\n", _("Check if the slave thread is running properly."));
00401   printf (" %s\n", "-w, --warning");
00402   printf ("    %s\n", _("Exit with WARNING status if slave server is more than INTEGER seconds"));
00403   printf ("    %s\n", _("behind master"));
00404   printf (" %s\n", "-c, --critical");
00405   printf ("    %s\n", _("Exit with CRITICAL status if slave server is more then INTEGER seconds"));
00406   printf ("    %s\n", _("behind master"));
00407 
00408   printf ("\n");
00409   printf (" %s\n", _("There are no required arguments. By default, the local database is checked"));
00410   printf (" %s\n", _("using the default unix socket. You can force TCP on localhost by using an"));
00411   printf (" %s\n", _("IP address or FQDN ('localhost' will use the socket as well)."));
00412 
00413        printf ("\n");
00414        printf ("%s\n", _("Notes:"));
00415        printf (" %s\n", _("You must specify -p with an empty string to force an empty password,"));
00416        printf (" %s\n", _("overriding any my.cnf settings."));
00417 
00418        printf (UT_SUPPORT);
00419 }
00420 
00421 
00422 void
00423 print_usage (void)
00424 {
00425        printf ("%s\n", _("Usage:"));
00426   printf (" %s [-d database] [-H host] [-P port] [-s socket]\n",progname);
00427   printf ("       [-u user] [-p password] [-S]\n");
00428 }