1 /******************************************************************************
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 $Id$
19 ******************************************************************************/
21 const char *progname = "check_procs";
22 const char *revision = "$Revision$";
23 const char *copyright = "2000-2004";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "popen.h"
28 #include "utils.h"
30 #include <pwd.h>
32 int process_arguments (int, char **);
33 int validate_arguments (void);
34 int check_thresholds (int);
35 int convert_to_seconds (char *);
36 void print_help (void);
37 void print_usage (void);
39 int wmax = -1;
40 int cmax = -1;
41 int wmin = -1;
42 int cmin = -1;
44 int options = 0; /* bitmask of filter criteria to test against */
45 #define ALL 1
46 #define STAT 2
47 #define PPID 4
48 #define USER 8
49 #define PROG 16
50 #define ARGS 32
51 #define VSZ 64
52 #define RSS 128
53 #define PCPU 256
54 #define ELAPSED 512
55 /* Different metrics */
56 char *metric_name;
57 enum metric {
58 METRIC_PROCS,
59 METRIC_VSZ,
60 METRIC_RSS,
61 METRIC_CPU,
62 METRIC_ELAPSED
63 };
64 enum metric metric = METRIC_PROCS;
66 int verbose = 0;
67 int uid;
68 int ppid;
69 int vsz;
70 int rss;
71 float pcpu;
72 char *statopts;
73 char *prog;
74 char *args;
75 char *fmt;
76 char *fails;
77 char tmp[MAX_INPUT_BUFFER];
81 int
82 main (int argc, char **argv)
83 {
84 char *input_buffer;
85 char *input_line;
86 char *procprog;
88 int procuid = 0;
89 int procppid = 0;
90 int procvsz = 0;
91 int procrss = 0;
92 int procseconds = 0;
93 float procpcpu = 0;
94 char procstat[8];
95 char procetime[MAX_INPUT_BUFFER];
96 char *procargs;
97 char *temp_string;
99 const char *zombie = "Z";
101 int resultsum = 0; /* bitmask of the filter criteria met by a process */
102 int found = 0; /* counter for number of lines returned in `ps` output */
103 int procs = 0; /* counter for number of processes meeting filter criteria */
104 int pos; /* number of spaces before 'args' in `ps` output */
105 int cols; /* number of columns in ps output */
106 int expected_cols = PS_COLS - 1;
107 int warn = 0; /* number of processes in warn state */
108 int crit = 0; /* number of processes in crit state */
109 int i = 0;
111 int result = STATE_UNKNOWN;
113 setlocale (LC_ALL, "");
114 bindtextdomain (PACKAGE, LOCALEDIR);
115 textdomain (PACKAGE);
117 input_buffer = malloc (MAX_INPUT_BUFFER);
118 procprog = malloc (MAX_INPUT_BUFFER);
120 asprintf (&metric_name, "PROCS");
121 metric = METRIC_PROCS;
123 if (process_arguments (argc, argv) == ERROR)
124 usage4 (_("Could not parse arguments"));
126 /* Set signal handling and alarm timeout */
127 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
128 usage4 (_("Cannot catch SIGALRM"));
129 }
130 alarm (timeout_interval);
132 if (verbose >= 2)
133 printf (_("CMD: %s\n"), PS_COMMAND);
135 child_process = spopen (PS_COMMAND);
136 if (child_process == NULL) {
137 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
138 return STATE_UNKNOWN;
139 }
141 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
142 if (child_stderr == NULL)
143 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
145 /* flush first line */
146 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
147 while ( input_buffer[strlen(input_buffer)-1] != '\n' )
148 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
150 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
151 asprintf (&input_line, "%s", input_buffer);
152 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
153 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
154 asprintf (&input_line, "%s%s", input_line, input_buffer);
155 }
157 if (verbose >= 3)
158 printf ("%s", input_line);
160 strcpy (procprog, "");
161 asprintf (&procargs, "%s", "");
163 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
165 /* Zombie processes do not give a procprog command */
166 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
167 cols = expected_cols;
168 }
169 if ( cols >= expected_cols ) {
170 resultsum = 0;
171 asprintf (&procargs, "%s", input_line + pos);
172 strip (procargs);
174 /* Some ps return full pathname for command. This removes path */
175 temp_string = strtok ((char *)procprog, "/");
176 while (temp_string) {
177 strcpy(procprog, temp_string);
178 temp_string = strtok (NULL, "/");
179 }
181 /* we need to convert the elapsed time to seconds */
182 procseconds = convert_to_seconds(procetime);
184 if (verbose >= 3)
185 printf ("%d %d %d %d %d %.2f %s %s %s %s\n",
186 procs, procuid, procvsz, procrss,
187 procppid, procpcpu, procstat,
188 procetime, procprog, procargs);
190 /* Ignore self */
191 if (strcmp (procprog, progname) == 0) {
192 continue;
193 }
195 if ((options & STAT) && (strstr (statopts, procstat)))
196 resultsum |= STAT;
197 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
198 resultsum |= ARGS;
199 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
200 resultsum |= PROG;
201 if ((options & PPID) && (procppid == ppid))
202 resultsum |= PPID;
203 if ((options & USER) && (procuid == uid))
204 resultsum |= USER;
205 if ((options & VSZ) && (procvsz >= vsz))
206 resultsum |= VSZ;
207 if ((options & RSS) && (procrss >= rss))
208 resultsum |= RSS;
209 if ((options & PCPU) && (procpcpu >= pcpu))
210 resultsum |= PCPU;
212 found++;
214 /* Next line if filters not matched */
215 if (!(options == resultsum || options == ALL))
216 continue;
218 procs++;
220 if (metric == METRIC_VSZ)
221 i = check_thresholds (procvsz);
222 else if (metric == METRIC_RSS)
223 i = check_thresholds (procrss);
224 /* TODO? float thresholds for --metric=CPU */
225 else if (metric == METRIC_CPU)
226 i = check_thresholds ((int)procpcpu);
227 else if (metric == METRIC_ELAPSED)
228 i = check_thresholds (procseconds);
230 if (metric != METRIC_PROCS) {
231 if (i == STATE_WARNING) {
232 warn++;
233 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
234 result = max_state (result, i);
235 }
236 if (i == STATE_CRITICAL) {
237 crit++;
238 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
239 result = max_state (result, i);
240 }
241 }
242 }
243 /* This should not happen */
244 else if (verbose) {
245 printf(_("Not parseable: %s"), input_buffer);
246 }
247 }
249 /* If we get anything on STDERR, at least set warning */
250 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
251 if (verbose)
252 printf (_("STDERR: %s"), input_buffer);
253 result = max_state (result, STATE_WARNING);
254 printf (_("System call sent warnings to stderr\n"));
255 }
257 (void) fclose (child_stderr);
259 /* close the pipe */
260 if (spclose (child_process)) {
261 printf (_("System call returned nonzero status\n"));
262 result = max_state (result, STATE_WARNING);
263 }
265 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
266 printf (_("Unable to read output\n"));
267 return result;
268 }
270 if ( result == STATE_UNKNOWN )
271 result = STATE_OK;
273 /* Needed if procs found, but none match filter */
274 if ( metric == METRIC_PROCS ) {
275 result = max_state (result, check_thresholds (procs) );
276 }
278 if ( result == STATE_OK ) {
279 printf ("%s %s: ", metric_name, _("OK"));
280 } else if (result == STATE_WARNING) {
281 printf ("%s %s: ", metric_name, _("WARNING"));
282 if ( metric != METRIC_PROCS ) {
283 printf (_("%d warn out of "), warn);
284 }
285 } else if (result == STATE_CRITICAL) {
286 printf ("%s %s: ", metric_name, _("CRITICAL"));
287 if (metric != METRIC_PROCS) {
288 printf (_("%d crit, %d warn out of "), crit, warn);
289 }
290 }
291 printf ("%d %s", procs, procs == 1 ? _("process") : _("processes"));
293 if (strcmp(fmt,"") != 0) {
294 printf (_(" with %s"), fmt);
295 }
297 if ( verbose >= 1 && strcmp(fails,"") )
298 printf (" [%s]", fails);
300 printf ("\n");
301 return result;
302 }
306 /* process command-line arguments */
307 int
308 process_arguments (int argc, char **argv)
309 {
310 int c = 1;
311 char *user;
312 struct passwd *pw;
313 int option = 0;
314 static struct option longopts[] = {
315 {"warning", required_argument, 0, 'w'},
316 {"critical", required_argument, 0, 'c'},
317 {"metric", required_argument, 0, 'm'},
318 {"timeout", required_argument, 0, 't'},
319 {"status", required_argument, 0, 's'},
320 {"ppid", required_argument, 0, 'p'},
321 {"command", required_argument, 0, 'C'},
322 {"vsz", required_argument, 0, 'z'},
323 {"rss", required_argument, 0, 'r'},
324 {"pcpu", required_argument, 0, 'P'},
325 {"elapsed", required_argument, 0, 'e'},
326 {"argument-array", required_argument, 0, 'a'},
327 {"help", no_argument, 0, 'h'},
328 {"version", no_argument, 0, 'V'},
329 {"verbose", no_argument, 0, 'v'},
330 {0, 0, 0, 0}
331 };
333 for (c = 1; c < argc; c++)
334 if (strcmp ("-to", argv[c]) == 0)
335 strcpy (argv[c], "-t");
337 while (1) {
338 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:",
339 longopts, &option);
341 if (c == -1 || c == EOF)
342 break;
344 switch (c) {
345 case '?': /* help */
346 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
347 print_usage ();
348 exit (STATE_UNKNOWN);
349 case 'h': /* help */
350 print_help ();
351 exit (STATE_OK);
352 case 'V': /* version */
353 print_revision (progname, revision);
354 exit (STATE_OK);
355 case 't': /* timeout period */
356 if (!is_integer (optarg))
357 usage2 (_("Timeout interval must be a positive integer"), optarg);
358 else
359 timeout_interval = atoi (optarg);
360 break;
361 case 'c': /* critical threshold */
362 if (is_integer (optarg))
363 cmax = atoi (optarg);
364 else if (sscanf (optarg, ":%d", &cmax) == 1)
365 break;
366 else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
367 break;
368 else if (sscanf (optarg, "%d:", &cmin) == 1)
369 break;
370 else
371 usage (_("Critical Process Count must be an integer!\n\n"));
372 break;
373 case 'w': /* warning threshold */
374 if (is_integer (optarg))
375 wmax = atoi (optarg);
376 else if (sscanf (optarg, ":%d", &wmax) == 1)
377 break;
378 else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
379 break;
380 else if (sscanf (optarg, "%d:", &wmin) == 1)
381 break;
382 else
383 usage (_("Warning Process Count must be an integer!\n\n"));
384 break;
385 case 'p': /* process id */
386 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
387 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
388 options |= PPID;
389 break;
390 }
391 usage2 (_("%s: Parent Process ID must be an integer!\n\n"), progname);
392 case 's': /* status */
393 if (statopts)
394 break;
395 else
396 statopts = optarg;
397 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
398 options |= STAT;
399 break;
400 case 'u': /* user or user id */
401 if (is_integer (optarg)) {
402 uid = atoi (optarg);
403 pw = getpwuid ((uid_t) uid);
404 /* check to be sure user exists */
405 if (pw == NULL)
406 usage2 (_("UID %s was not found\n"), optarg);
407 }
408 else {
409 pw = getpwnam (optarg);
410 /* check to be sure user exists */
411 if (pw == NULL)
412 usage2 (_("User name %s was not found\n"), optarg);
413 /* then get uid */
414 uid = pw->pw_uid;
415 }
416 user = pw->pw_name;
417 asprintf (&fmt, _("%s%sUID = %d (%s)"), (fmt ? fmt : ""), (options ? ", " : ""),
418 uid, user);
419 options |= USER;
420 break;
421 case 'C': /* command */
422 /* TODO: allow this to be passed in with --metric */
423 if (prog)
424 break;
425 else
426 prog = optarg;
427 asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
428 prog);
429 options |= PROG;
430 break;
431 case 'a': /* args (full path name with args) */
432 /* TODO: allow this to be passed in with --metric */
433 if (args)
434 break;
435 else
436 args = optarg;
437 asprintf (&fmt, _("%s%sargs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), args);
438 options |= ARGS;
439 break;
440 case 'r': /* RSS */
441 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
442 asprintf (&fmt, _("%s%sRSS >= %d"), (fmt ? fmt : ""), (options ? ", " : ""), rss);
443 options |= RSS;
444 break;
445 }
446 usage2 (_("%s: RSS must be an integer!\n\n"), progname);
447 case 'z': /* VSZ */
448 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
449 asprintf (&fmt, _("%s%sVSZ >= %d"), (fmt ? fmt : ""), (options ? ", " : ""), vsz);
450 options |= VSZ;
451 break;
452 }
453 usage2 (_("%s: VSZ must be an integer!\n\n"), progname);
454 case 'P': /* PCPU */
455 /* TODO: -P 1.5.5 is accepted */
456 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
457 asprintf (&fmt, _("%s%sPCPU >= %.2f"), (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
458 options |= PCPU;
459 break;
460 }
461 usage2 (_("%s: PCPU must be a float!\n\n"), progname);
462 case 'm':
463 asprintf (&metric_name, "%s", optarg);
464 if ( strcmp(optarg, "PROCS") == 0) {
465 metric = METRIC_PROCS;
466 break;
467 }
468 else if ( strcmp(optarg, "VSZ") == 0) {
469 metric = METRIC_VSZ;
470 break;
471 }
472 else if ( strcmp(optarg, "RSS") == 0 ) {
473 metric = METRIC_RSS;
474 break;
475 }
476 else if ( strcmp(optarg, "CPU") == 0 ) {
477 metric = METRIC_CPU;
478 break;
479 }
480 else if ( strcmp(optarg, "ELAPSED") == 0) {
481 metric = METRIC_ELAPSED;
482 break;
483 }
485 printf (_("%s: metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!\n\n"),
486 progname);
487 print_usage ();
488 exit (STATE_UNKNOWN);
489 case 'v': /* command */
490 verbose++;
491 break;
492 }
493 }
495 c = optind;
496 if (wmax == -1 && argv[c])
497 wmax = atoi (argv[c++]);
498 if (cmax == -1 && argv[c])
499 cmax = atoi (argv[c++]);
500 if (statopts == NULL && argv[c]) {
501 asprintf (&statopts, "%s", argv[c++]);
502 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
503 options |= STAT;
504 }
506 return validate_arguments ();
507 }
511 int
512 validate_arguments ()
513 {
515 if (wmax >= 0 && wmin == -1)
516 wmin = 0;
517 if (cmax >= 0 && cmin == -1)
518 cmin = 0;
519 if (wmax >= wmin && cmax >= cmin) { /* standard ranges */
520 if (wmax > cmax && cmax != -1) {
521 printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
522 return ERROR;
523 }
524 if (cmin > wmin && wmin != -1) {
525 printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
526 return ERROR;
527 }
528 }
530 /* if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
531 /* printf ("At least one threshold must be set\n"); */
532 /* return ERROR; */
533 /* } */
535 if (options == 0)
536 options = ALL;
538 if (statopts==NULL)
539 statopts = strdup("");
541 if (prog==NULL)
542 prog = strdup("");
544 if (args==NULL)
545 args = strdup("");
547 if (fmt==NULL)
548 fmt = strdup("");
550 if (fails==NULL)
551 fails = strdup("");
553 return options;
554 }
558 /* Check thresholds against value */
559 int
560 check_thresholds (int value)
561 {
562 if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
563 return OK;
564 }
565 else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
566 if (value > cmax && value < cmin)
567 return STATE_CRITICAL;
568 }
569 else if (cmax >= 0 && value > cmax) {
570 return STATE_CRITICAL;
571 }
572 else if (cmin >= 0 && value < cmin) {
573 return STATE_CRITICAL;
574 }
576 if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
577 if (value > wmax && value < wmin) {
578 return STATE_WARNING;
579 }
580 }
581 else if (wmax >= 0 && value > wmax) {
582 return STATE_WARNING;
583 }
584 else if (wmin >= 0 && value < wmin) {
585 return STATE_WARNING;
586 }
587 return STATE_OK;
588 }
593 /* convert the elapsed time to seconds */
594 int
595 convert_to_seconds(char *etime) {
597 char *ptr;
598 int total;
600 int hyphcnt;
601 int coloncnt;
602 int days;
603 int hours;
604 int minutes;
605 int seconds;
607 hyphcnt = 0;
608 coloncnt = 0;
609 days = 0;
610 hours = 0;
611 minutes = 0;
612 seconds = 0;
614 for (ptr = etime; *ptr != '\0'; ptr++) {
616 if (*ptr == '-') {
617 hyphcnt++;
618 continue;
619 }
620 if (*ptr == ':') {
621 coloncnt++;
622 continue;
623 }
624 }
626 if (hyphcnt > 0) {
627 sscanf(etime, "%d-%d:%d:%d",
628 &days, &hours, &minutes, &seconds);
629 /* linux 2.6.5/2.6.6 reporting some processes with infinite
630 * elapsed times for some reason */
631 if (days == 49710) {
632 return 0;
633 }
634 } else {
635 if (coloncnt == 2) {
636 sscanf(etime, "%d:%d:%d",
637 &hours, &minutes, &seconds);
638 } else if (coloncnt == 1) {
639 sscanf(etime, "%d:%d",
640 &minutes, &seconds);
641 }
642 }
644 total = (days * 86400) +
645 (hours * 3600) +
646 (minutes * 60) +
647 seconds;
649 if (verbose >= 3) {
650 printf("seconds: %d\n", total);
651 }
652 return total;
653 }
657 void
658 print_help (void)
659 {
660 print_revision (progname, revision);
662 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>");
663 printf (COPYRIGHT, copyright, email);
665 printf(_("\
666 Checks all processes and generates WARNING or CRITICAL states if the specified\n\
667 metric is outside the required threshold ranges. The metric defaults to number\n\
668 of processes. Search filters can be applied to limit the processes to check.\n\n"));
670 print_usage ();
672 printf(_("\n\
673 Required Arguments:\n\
674 -w, --warning=RANGE\n\
675 Generate warning state if metric is outside this range\n\
676 -c, --critical=RANGE\n\
677 Generate critical state if metric is outside this range\n"));
679 printf(_("\n\
680 Optional Arguments:\n\
681 -m, --metric=TYPE\n\
682 Check thresholds against metric. Valid types:\n\
683 PROCS - number of processes (default)\n\
684 VSZ - virtual memory size\n\
685 RSS - resident set memory size\n\
686 CPU - percentage cpu\n"));
687 /* only linux etime is support currently */
688 #if defined( __linux__ )
689 printf(_("\
690 ELAPSED - time elapsed in seconds\n"));
691 #endif /* defined(__linux__) */
692 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
694 printf(_("\
695 -v, --verbose\n\
696 Extra information. Up to 3 verbosity levels\n"));
698 printf(_("\n\
699 Optional Filters:\n\
700 -s, --state=STATUSFLAGS\n\
701 Only scan for processes that have, in the output of `ps`, one or\n\
702 more of the status flags you specify (for example R, Z, S, RS,\n\
703 RSZDT, plus others based on the output of your 'ps' command).\n\
704 -p, --ppid=PPID\n\
705 Only scan for children of the parent process ID indicated.\n\
706 -z, --vsz=VSZ\n\
707 Only scan for processes with vsz higher than indicated.\n\
708 -r, --rss=RSS\n\
709 Only scan for processes with rss higher than indicated.\n"));
711 printf(_("\
712 -P, --pcpu=PCPU\n\
713 Only scan for processes with pcpu higher than indicated.\n\
714 -u, --user=USER\n\
715 Only scan for processes with user name or ID indicated.\n\
716 -a, --argument-array=STRING\n\
717 Only scan for processes with args that contain STRING.\n\
718 -C, --command=COMMAND\n\
719 Only scan for exact matches of COMMAND (without path).\n"));
721 printf(_("\n\
722 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
723 specified 'max:min', a warning status will be generated if the\n\
724 count is inside the specified range\n\n"));
726 printf(_("\
727 This plugin checks the number of currently running processes and\n\
728 generates WARNING or CRITICAL states if the process count is outside\n\
729 the specified threshold ranges. The process count can be filtered by\n\
730 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
731 be the total number of running processes\n\n"));
733 printf(_("\
734 Examples:\n\
735 check_procs -w 2:2 -c 2:1024 -C portsentry\n\
736 Warning if not two processes with command name portsentry. Critical\n\
737 if < 2 or > 1024 processes\n\n\
738 check_procs -w 10 -a '/usr/local/bin/perl' -u root\n\
739 Warning alert if > 10 processes with command arguments containing \n\
740 '/usr/local/bin/perl' and owned by root\n\n\
741 check_procs -w 50000 -c 100000 --metric=VSZ\n\
742 Alert if vsz of any processes over 50K or 100K\n\
743 check_procs -w 10 -c 20 --metric=CPU\n\
744 Alert if cpu of any processes over 10%% or 20%%\n\n"));
746 printf (_(UT_SUPPORT));
747 }
749 void
750 print_usage (void)
751 {
752 printf ("\
753 Usage: %s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n\
754 [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n\
755 [-C command] [-t timeout] [-v]\n", progname);
756 }