Back to index

nagios-plugins  1.4.16
check_procs.c
Go to the documentation of this file.
00001 /*                                                                          
00002         Source: check_procs.c
00003         Author: Adam G. Bowen (agbowen@bealenet.com)
00004         $Revision: 1.4 $
00005         $Date: 1999/05/17 14:35:26 $
00006  
00007  * Program: Process check plugin for NetSaint
00008  * License: GPL
00009  * Copyright (c) 1999 Adam G. Bowen (agbowen@bealenet.com)
00010  *
00011  * Description:
00012  *
00013  * This plugin will check the number of processes running on the remote host at
00014  * ipaddress and generate an alert if number is above one of the threshold
00015  * values.
00016  *
00017  * Other errors result in a STATE_UNKNOWN return.
00018  *
00019  * Command line:
00020  *
00021  * check_procs ipaddress sys_type
00022  * check_procs ipaddress sys_type <state_flag>
00023  * check_procs ipaddress sys_type <warn_#> <crit_#>
00024  * check_procs ipaddress sys_type <warn_#> <crit_#> <state_flag>
00025  *
00026  * Required input:
00027  *
00028  * ipaddress = The ipaddress of the remote system to run the check on.
00029  * sys_type = The remote system type.
00030  *
00031  * Optional input:
00032  *
00033  * <warn_#> = Number of processes necessary to result in a WARNING state.
00034  * <crit_#> = Number of processes necessary to result in a CRITICAL state.
00035  * <state_flag> = Only report on processes in this state.
00036  *
00037  * Notes:
00038  *
00039  * If <warn_#>, <crit_#> and <state_flag> are not passed on the command line,
00040  * they will be set to the default values in the check_procs config file.
00041  *
00042  * If <warn_#> and <crit_#> are passed on the command line and <state_flag> is
00043  * not passed on the command line, <state_flag> is set to ALL.
00044  *
00045  * If <state_flag> is passed on the command line and <warn_#> and <crit_#> are
00046  * not passed on the command line, <warn_#> and <crit_#> are set to default
00047  * values in the check_procs config file.
00048  *
00049  * sys_type is used to determine which config file to use to generate the
00050  * remote command.
00051  *
00052  * The configuration file /usr/local/netsaint/config/check_procs/local
00053  * contains the following values:
00054  *
00055  * RSH_COMMAND|<location of rsh command on netsaint system>|
00056  * AWK_COMMAND|<location of awk command on netsaint system>|
00057  * WARN_PROCS|<default number of processes need to generate a warning>|
00058  * CRIT_PROCS|<default number of processes need to generate a critical>|
00059  *
00060  * The configuration file /usr/local/netsaint/config/check_procs/<sys_type>
00061  * contains the following values:
00062  *
00063  * PS_COMMAND|<location of ps command on system sys_type>|
00064  * PS_OPTIONS|<options for ps command to retreive required info>|
00065  * AWK_OPTIONS|<options for awk command to retreive required info>|
00066  * <flag name>|<flag on system sys_type>| * see below for explanation.
00067  *
00068  * Process state flags.
00069  *
00070  * All unix systems do not uses the same letter for the same state.  For 
00071  * example DEC osf1 use U for an Uninterruptible sleeping process.  However,
00072  * linux uses D for the same process.  In order for the process check to be
00073  * performed on heterogenious hosts, there had to be mapping of flags.  This
00074  * is accomplished by mapping the state flag passed on the command line to a
00075  * flag name.  Once the flag has been mapped to a name, the configuration file
00076  * /usr/local/netsaint/config/check_procs/<sys_type> will be searhed for an
00077  * entry containing <flag_name> and the <flag on system sys_type> will be 
00078  * mapped to state flag.
00079  *
00080  * The following list contains the command line flag and its' mapped flag_name:
00081  *
00082  * Command Line Flag | Flag Name
00083  *
00084  *      A            | ACTIVE
00085  *      C            | CANCELED
00086  *      H            | HALTED
00087  *      I            | IDLE
00088  *      O            | NON_EXISTANT
00089  *      P            | PROCESSING
00090  *      R            | RUNABLE
00091  *      S            | SLEEP
00092  *      T            | STOPPED
00093  *      U            | UNINT_SLEEP
00094  *      W            | SWAPPED
00095  *      Z            | ZOMBIE
00096  *
00097  * Note:
00098  * Not all systems will have all flags.
00099  *
00100  * $Log: check_procs.c,v $
00101  * Revision 1.4  1999/05/17 14:35:26  netsaint
00102  * Changed the plugin to use a seperate config directory.  This directory is the
00103  * CONFIG_DIR/command_name directory.
00104  *
00105  * Revision 1.3  1999/05/14 03:01:17  netsaint
00106  * Added the following integer variable:
00107  *     socket_name
00108  * Changed the call check_net to open_socket.  Added a call to recv_socket and
00109  * close_socket.  The check_net subroutine was changed to provide more
00110  * flexibility.
00111  * Added a call to the subroutine get_command_name.
00112  * Changed the error checking routines to ensure that any error cause the
00113  * program to terminate.
00114  *
00115  * Revision 1.2  1999/05/07 15:30:26  netsaint
00116  * Removed the char variable error_buffer and the FILE *error_fp variable.
00117  * These variables are no longer needed since the printing of the error file is
00118  * handled in a subroutine.
00119  * Added a call to the check_output_file subroutine.  This routine checks the
00120  * status of the output file.  Also removed the struct stat file_stat variable.
00121  * Added a call to the check_consistency subroutine.  This subroutine checks
00122  * that the warn value is less than the critical value.
00123  *
00124  * Revision 1.1  1999/05/03 20:23:16  netsaint
00125  * Initial revision
00126  *
00127 */
00128 
00129 #include "/usr/local/src/netsaint/include/plugins.h"
00130 
00131 int main(int argc, char *argv[])
00132 {
00133   char expected[MAX_CHARS]="";
00134   char state_flag[MAX_CHARS]="";
00135   char state_label[MAX_CHARS]="All";
00136 
00137   char awk_command[MAX_CHARS];
00138   char awk_options[MAX_CHARS];
00139   char command_line[MAX_CHARS];
00140   char command_name[MAX_CHARS];
00141   char config_file_local[MAX_CHARS];
00142   char config_file_net[MAX_CHARS];
00143   char config_file_remote[MAX_CHARS];
00144   char error_file[MAX_CHARS];
00145   char input_buffer[MAX_CHARS];
00146   char ip_address[MAX_CHARS];
00147   char out_put_file[MAX_CHARS];
00148   char port_telnet[MAX_CHARS];
00149   char procs_crit[MAX_CHARS];
00150   char procs_warn[MAX_CHARS];
00151   char protocol[MAX_CHARS];
00152   char ps_command[MAX_CHARS];
00153   char ps_options[MAX_CHARS];
00154   char rsh_command[MAX_CHARS];
00155   char system_name[MAX_CHARS];
00156   char temp_value[MAX_CHARS];
00157 
00158   FILE *out_put_fp;
00159 
00160   int crit_procs;
00161   int get_all;
00162   int get_defaults;
00163   int process_count;
00164   int result;
00165   int return_value;
00166   int socket_name;
00167   int telnet_port;
00168   int warn_procs;
00169 
00170   /* Initialize alarm signal handling */
00171 
00172   signal(SIGALRM,alarm_signal);
00173 
00174   strcpy(command_name,get_command_name(argv[0]));
00175   if(!((argc==3) || (argc == 4) || (argc == 5) || (argc==6)))
00176   {
00177     printf("\n");
00178     printf(" Incorrect number of arguments supplied\n");
00179     printf("\n");
00180     printf(" Process check plugin for NetSaint\n");
00181     printf(" Copyright (c) 1999 Adam G. Bowen (agbowen@bealenet.com)\n");
00182     printf(" $Revision: 1.4 $\n");
00183     printf(" Last Modified $Date: 1999/05/17 14:35:26 $\n");
00184     printf(" License: GPL\n");
00185     printf("\n");
00186     printf(" Description:\n");
00187     printf("\n");
00188     printf(" This plugin will check the number of processes running on the remote host at\n");
00189     printf(" ipaddress and generate an alert if number is above one of the threshold\n");
00190     printf(" values.\n");
00191     printf("\n");
00192     printf(" Usage: %s ipaddress sys_type\n",command_name);
00193     printf(" Usage: %s ipaddress sys_type <state_flag>\n",command_name);
00194     printf(" Usage: %s ipaddress sys_type <warn_#> <crit_#>\n",command_name);
00195     printf(" Usage: %s ipaddress sys_type <warn_#> <crit_#> <state_flag>\n",command_name);
00196     printf("\n");
00197     printf(" Required input:\n");
00198     printf("\n");
00199     printf(" ipaddress = The ipaddress of the remote system to run the check on.\n");
00200     printf(" sys_type = The remote system type.\n");
00201     printf("\n");
00202     printf(" Optional input:\n");
00203     printf("\n");
00204     printf(" <warn_#> =Number of processes necessary to result in a WARNING state.\n");
00205     printf(" <crit_#> = Number of processes necessary to result in a CRITICAL state.\n");
00206     printf(" <state_flag> = Only report on processes in this state.\n");
00207     printf("\n");
00208     printf(" If <warn_#>, <crit_#> and <state_flag> are not passed on the command line,\n");
00209     printf(" they will be set to the default values in the %s config file.\n",command_name);
00210     printf("\n");
00211     printf(" If <warn_#> and <crit_#> are passed on the command line and <state_flag> is\n");
00212     printf(" not passed on the command line, <state_flag> is set to ALL.\n");
00213     printf("\n");
00214     printf("  If <state_flag> is passed on the command line and <warn_#> and <crit_#> are\n");
00215     printf(" not passed on the command line, <warn_#> and <crit_#> are set to default\n");
00216     printf(" values in the %s config file.\n", command_name);
00217     printf("\n");
00218     printf(" sys_type is used to determine which config file to use to generate the\n");
00219     printf(" remote command.\n");
00220     printf("\n");
00221     return_value = STATE_UNKNOWN;
00222   }
00223   else
00224   {
00225     /* Set up config files and get the command line information */
00226 
00227     strcpy(ip_address,argv[1]);
00228     strcpy(system_name,argv[2]);
00229 
00230     strcpy(config_file_local,CONFIG_DIR);
00231     strcpy(config_file_remote,CONFIG_DIR);
00232     strcpy(config_file_net,CONFIG_DIR);
00233     strcat(config_file_local,command_name);
00234     strcat(config_file_remote,command_name);
00235     strcat(config_file_net,CHECK_TELNET);
00236     strcat(config_file_local,"/local");
00237     strcat(config_file_remote,"/");
00238     strcat(config_file_net,"/");
00239     strcat(config_file_remote,system_name);
00240     strcat(config_file_net,system_name);
00241 
00242     if(argc == 3)
00243     {
00244       get_defaults = TRUE;
00245       get_all = TRUE;
00246     }
00247     else if(argc == 4)
00248     {
00249       get_defaults = TRUE;
00250       get_all = FALSE;
00251       strupr(strncpy(state_flag,argv[3],1));
00252     }
00253     else if(argc == 5)
00254     {
00255       get_defaults = FALSE;
00256       get_all = TRUE;
00257       strcpy(procs_warn,argv[3]);
00258       strcpy(procs_crit,argv[4]);
00259     }
00260     else
00261     {
00262       get_defaults = FALSE;
00263       get_all = FALSE;
00264       strcpy(procs_warn,argv[3]);
00265       strcpy(procs_crit,argv[4]);
00266       strupr(strncpy(state_flag,argv[5],1));
00267     }
00268 
00269     /* Check if config files exist */
00270 
00271     if (access(config_file_local, EXISTS) != 0 )
00272     {
00273       printf("Config file %s does not exist!\n",config_file_local);
00274       return_value = STATE_UNKNOWN;
00275     }
00276     else if (access(config_file_remote, EXISTS) != 0 )
00277     {
00278       printf("Config file %s does not exist!\n",config_file_remote);
00279       return_value = STATE_UNKNOWN;
00280     }
00281     else if (access(config_file_net, EXISTS) != 0 )
00282     {
00283       printf("Config file %s does not exist!\n",config_file_net);
00284       return_value = STATE_UNKNOWN;
00285     }
00286     else
00287     {
00288       if(!get_all)
00289       {
00290         if(strcmp(state_flag,"A") == 0)
00291         {
00292           strcpy(state_label,"Active");
00293           return_value=get_var("ACTIVE", config_file_remote, temp_value);
00294         }
00295         else if(strcmp(state_flag,"C") == 0)
00296         {
00297           strcpy(state_label,"Canceled");
00298           return_value=get_var("CANCELED", config_file_remote, temp_value);
00299         }
00300         else if(strcmp(state_flag,"H") == 0)
00301         {
00302           strcpy(state_label,"Halted");
00303           return_value=get_var("HALTED", config_file_remote, temp_value);
00304         }
00305         else if(strcmp(state_flag,"I") == 0)
00306         {
00307           strcpy(state_label,"Idle");
00308           return_value=get_var("IDLE", config_file_remote, temp_value);
00309         }
00310         else if(strcmp(state_flag,"O") == 0)
00311         {
00312           strcpy(state_label,"Non existant");
00313           return_value=get_var("NON_EXISTANT", config_file_remote, temp_value);
00314         }
00315         else if(strcmp(state_flag,"P") == 0)
00316         {
00317           strcpy(state_label,"Processing");
00318           return_value=get_var("PROCESSING", config_file_remote, temp_value);
00319         }
00320         else if(strcmp(state_flag,"R") == 0)
00321         {
00322           strcpy(state_label,"Runable");
00323           return_value=get_var("RUNABLE", config_file_remote, temp_value);
00324         }
00325         else if(strcmp(state_flag,"S") == 0)
00326         {
00327           strcpy(state_label,"Sleep");
00328           return_value=get_var("SLEEP", config_file_remote, temp_value);
00329         }
00330         else if(strcmp(state_flag,"T") == 0)
00331         {
00332           strcpy(state_label,"Stopped");
00333           return_value=get_var("STOPPED", config_file_remote, temp_value);
00334         }
00335         else if(strcmp(state_flag,"U") == 0)
00336         {
00337           strcpy(state_label,"Uninterruptible Sleep");
00338           return_value=get_var("UNINT_SLEEP", config_file_remote, temp_value);
00339         }
00340         else if(strcmp(state_flag,"W") == 0)
00341         {
00342           strcpy(state_label,"Swapped");
00343           return_value=get_var("SWAPPED", config_file_remote, temp_value);
00344         }
00345         else if(strcmp(state_flag,"Z") == 0)
00346         {
00347           strcpy(state_label,"Zombie");
00348           return_value=get_var("ZOMBIE", config_file_remote, temp_value);
00349         }
00350         else
00351         {
00352           printf("%s is an unknow state flag.\n",state_flag);
00353           return_value = STATE_UNKNOWN;
00354         }
00355         if(strcmp(temp_value, "NOT_FOUND") == 0)
00356         {
00357           printf("%s state information not found in config file %s!\n",state_label, config_file_remote);
00358           return_value = STATE_UNKNOWN;
00359         } 
00360         else
00361         {
00362           strcpy(state_flag,temp_value);
00363         }
00364       }
00365       else
00366       {
00367         return_value = STATE_OK;
00368       }
00369       if(return_value == STATE_OK)
00370       {
00371 
00372         /* Local config file variables */
00373 
00374         if((get_defaults == TRUE) && ((return_value=get_var("WARN_PROCS", config_file_local, procs_warn)) != STATE_OK))
00375         {
00376           printf("WARN_PROCS entry not found in config file %s!\n",config_file_local);
00377         }
00378         else if((get_defaults == TRUE) && ((return_value=get_var("CRIT_PROCS", config_file_local, procs_crit)) != STATE_OK))
00379         {
00380           printf("CRIT_PROCS entry not found in config file %s!\n",config_file_local);
00381         }
00382         else if((return_value=get_var("RSH_COMMAND", config_file_local, rsh_command)) != STATE_OK)
00383         {
00384           printf("RSH_COMMAND entry not found in config file %s!\n", config_file_local);
00385         }
00386         else if((return_value=get_var("AWK_COMMAND", config_file_local, awk_command)) != STATE_OK)
00387         {
00388           printf("AWK_COMMAND entry not found in config file %s!\n", config_file_local);
00389         }
00390 
00391         /* Remote config file variables */
00392 
00393         else if((return_value=get_var("PS_COMMAND", config_file_remote, ps_command)) != STATE_OK)
00394         {
00395           printf("PS_COMMAND entry not found in config file %s!\n", config_file_remote);
00396         }
00397         else if((return_value=get_var("PS_OPTIONS", config_file_remote, ps_options)) != STATE_OK)
00398         {
00399           printf("PS_OPTIONS entry not found in config file %s!\n",config_file_remote);
00400         }
00401         else if((return_value=get_var("AWK_OPTIONS", config_file_remote, awk_options)) != STATE_OK)
00402         {
00403           printf("AWK_OPTIONS entry not found in config file %s!\n",config_file_remote);
00404         }
00405 
00406         /* Network config file variables */
00407 
00408         else if((return_value=get_var("TELNET_PORT", config_file_net, port_telnet)) != STATE_OK)
00409         {
00410           printf("TELNET_PORT entry not found in config file %s!\n",config_file_net);
00411         }
00412         else if((return_value=get_var("TELNET_PROTO", config_file_net, protocol)) != STATE_OK)
00413         {
00414           printf("TELNET_PROTO entry not found in config file %s!\n",config_file_net);
00415         }
00416         else
00417         {
00418   
00419           /* Check alert level consistency */
00420 
00421           warn_procs=atoi(procs_warn);
00422           crit_procs=atoi(procs_crit);
00423           return_value = check_consistency(warn_procs, crit_procs);
00424           if(return_value == STATE_OK)
00425           {
00426 
00427             /* Check the network */
00428 
00429             telnet_port=atoi(port_telnet);
00430             alarm(TIME_OUT);
00431             if((result=open_socket(&socket_name, ip_address, telnet_port, protocol)) != STATE_OK)
00432             {
00433               return_value=exit_error(result,ip_address,protocol,telnet_port);
00434             }
00435             else if((result=recv_socket(&socket_name, expected)) != STATE_OK)
00436             {
00437               return_value=exit_error(result,ip_address,protocol,telnet_port);
00438             }
00439             else if((result=close_socket(&socket_name)) != STATE_OK)
00440             {
00441               return_value=exit_error(result,ip_address,protocol,telnet_port);
00442             }
00443             else
00444             {
00445               alarm(0);
00446 
00447               /* Generate a out_put and error file names */
00448   
00449               strcpy(out_put_file, tmpnam(NULL));
00450               strcpy(error_file, tmpnam(NULL));
00451    
00452               /* Set the command line and arguments to use for the check */
00453   
00454               sprintf(command_line,"%s %s %s %s </dev/null 2>%s|%s %s >%s 2>>%s",rsh_command, ip_address, ps_command, ps_options, error_file, awk_command, awk_options, out_put_file, error_file);
00455   
00456               /* Run the command */
00457     
00458               system(command_line);
00459   
00460               return_value=check_output_file(out_put_file);
00461               if (return_value != STATE_OK)
00462               {
00463                 print_error(error_file);
00464               }
00465               else
00466               {
00467                 out_put_fp=fopen(out_put_file,"r");
00468   
00469                 /* Retrive single line from output file */
00470   
00471                 fgets(input_buffer,MAX_CHARS-1,out_put_fp);
00472                 process_count = 0;
00473   
00474                 while(fgets(input_buffer,MAX_CHARS-1,out_put_fp) != NULL)
00475                 {
00476                   if(get_all)
00477                   {
00478                     process_count++;
00479                   }
00480                   else if(strstr(input_buffer,state_flag) !=0)
00481                   {
00482                     process_count++;
00483                   }
00484                 }
00485   
00486                 /* Close output file */
00487   
00488                 fclose(out_put_fp);
00489     
00490                 /* Check the process count against warning and critical levels */
00491     
00492                 if(process_count >= crit_procs)
00493                 {
00494                   return_value=STATE_CRITICAL;
00495                 }
00496                 else if(process_count >= warn_procs)
00497                 {
00498                   return_value=STATE_WARNING;
00499                 }
00500       
00501                 if(return_value==STATE_OK)
00502                 {
00503                   printf("%s processes count ok - %d processes in %s state\n", state_label,process_count,state_label);
00504                 }
00505                 else
00506                 {
00507                   printf("%s processes count error - %d processes in %s state\n", state_label,process_count,state_label);
00508                 }
00509               }
00510     
00511               /* Remove the output and error files */
00512     
00513               remove(out_put_file);
00514               remove(error_file);
00515   
00516             }
00517           }
00518         }
00519       }
00520     }
00521   }
00522   return return_value;
00523 }