diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 553430596656601b7fb2923638176ef04b79c970..a7dd5cce02e331e27c82c61f5c1e29f1dabdcb0e 100644 (file)
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
/******************************************************************************
- *
- * CHECK_DISK.C
- *
- * Program: Disk space plugin for Nagios
- * License: GPL
- * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
- * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
- *
- * $Id$
- *
- * Description:
- *
- * This plugin will use the /bin/df command to check the free space on
- * currently mounted filesystems. If the percent used disk space is
- * above <c_dfp>, a STATE_CRITICAL is returned. If the percent used
- * disk space is above <w_dfp>, a STATE_WARNING is returned. If the
- * speicified filesystem cannot be read, a STATE_CRITICAL is returned,
- * other errors with reading the output result in a STATE_UNKNOWN
- * error.
- *
- * Notes:
- * - IRIX support added by Charlie Cook 4-16-1999
- * - Modifications by Karl DeBisschop 1999-11-24
- * reformat code to 80 char screen width
- * set STATE_WARNING if stderr is written or spclose status set
- * set default result to STAT_UNKNOWN
- * initailize usp to -1, eliminate 'found' variable
- * accept any filename/filesystem
- * use sscanf, drop while loop
- *
- *****************************************************************************/
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+const char *progname = "check_disk";
+const char *revision = "$Revision$";
+const char *copyright = "1999-2003";
+const char *authors = "Nagios Plugin Development Team";
+const char *email = "nagiosplug-devel@lists.sourceforge.net";
+
+const char *summary = "\
+This plugin checks the amount of used disk space on a mounted file system\n\
+and generates an alert if free space is less than one of the threshold values.";
+
+const char *option_summary = "\
+-w limit -c limit [-p path | -x device] [-t timeout] [-m] [-e]\n\
+ [-v] [-q]";
+
+const char *options = "\
+ -w, --warning=INTEGER\n\
+ Exit with WARNING status if less than INTEGER kilobytes of disk are free\n\
+ -w, --warning=PERCENT%%\n\
+ Exit with WARNING status if less than PERCENT of disk space is free\n\
+ -c, --critical=INTEGER\n\
+ Exit with CRITICAL status if less than INTEGER kilobytes of disk are free\n\
+ -c, --critical=PERCENT%%\n\
+ Exit with CRITCAL status if less than PERCENT of disk space is free\n\
+ -p, --path=PATH, --partition=PARTTION\n\
+ Path or partition (checks all mounted partitions if unspecified)\n\
+ -m, --mountpoint\n\
+ Display the mountpoint instead of the partition\n\
+ -x, --exclude_device=PATH\n\
+ Ignore device (only works if -p unspecified)\n\
+ -e, --errors-only\n\
+ Display only devices/mountpoints with errors\n\
+ -v, --verbose\n\
+ Show details for command-line debugging (do not use with nagios server)\n\
+ -h, --help\n\
+ Print detailed help screen\n\
+ -V, --version\n\
+ Print version information\n";
#include "common.h"
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <assert.h>
#include "popen.h"
#include "utils.h"
#include <stdarg.h>
+#include "../lib/fsusage.h"
+#include "../lib/mountlist.h"
+
+/* If nonzero, show inode information. */
+static int inode_format;
+
+/* If nonzero, show even filesystems with zero size or
+ uninteresting types. */
+static int show_all_fs;
+
+/* If nonzero, show only local filesystems. */
+static int show_local_fs;
+
+/* If nonzero, output data for each filesystem corresponding to a
+ command line argument -- even if it's a dummy (automounter) entry. */
+static int show_listed_fs;
+
+/* If positive, the units to use when printing sizes;
+ if negative, the human-readable base. */
+static int output_block_size;
+
+/* If nonzero, invoke the `sync' system call before getting any usage data.
+ Using this option can make df very slow, especially with many or very
+ busy disks. Note that this may make a difference on some systems --
+ SunOs4.1.3, for one. It is *not* necessary on Linux. */
+static int require_sync = 0;
+
+/* A filesystem type to display. */
+
+struct name_list
+{
+ char *name;
+ struct name_list *name_next;
+};
+
+/* Linked list of filesystem types to display.
+ If `fs_select_list' is NULL, list all types.
+ This table is generated dynamically from command-line options,
+ rather than hardcoding into the program what it thinks are the
+ valid filesystem types; let the user specify any filesystem type
+ they want to, and if there are any filesystems of that type, they
+ will be shown.
+
+ Some filesystem types:
+ 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
+
+static struct name_list *fs_select_list;
+
+/* Linked list of filesystem types to omit.
+ If the list is empty, don't exclude any types. */
+
+static struct name_list *fs_exclude_list;
+
+static struct name_list *dp_exclude_list;
+
+static struct name_list *path_select_list;
+
+static struct name_list *dev_select_list;
-#define REVISION "$Revision$"
-#define COPYRIGHT "2000-2002"
+/* Linked list of mounted filesystems. */
+static struct mount_entry *mount_list;
+
+/* For long options that have no equivalent short option, use a
+ non-character as a pseudo short option, starting with CHAR_MAX + 1. */
+enum
+{
+ SYNC_OPTION = CHAR_MAX + 1,
+ NO_SYNC_OPTION,
+ BLOCK_SIZE_OPTION
+};
+
+#ifdef _AIX
+ #pragma alloca
+#endif
int process_arguments (int, char **);
int validate_arguments (void);
int check_disk (int usp, int free_disk);
+int walk_name_list (struct name_list *list, const char *name);
void print_help (void);
void print_usage (void);
-const char *PROGNAME = "check_disk";
-
int w_df = -1;
int c_df = -1;
float w_dfp = -1.0;
char *path = "";
char *exclude_device = "";
int verbose = 0;
+int erronly = FALSE;
int display_mntp = FALSE;
+/* Linked list of mounted filesystems. */
+static struct mount_entry *mount_list;
int
main (int argc, char **argv)
char file_system[MAX_INPUT_BUFFER];
char mntp[MAX_INPUT_BUFFER];
char *output = "";
+ char *details = "";
- if (process_arguments (argc, argv) != OK)
- usage ("Could not parse arguments\n");
-
- asprintf (&command_line, "%s %s", DF_COMMAND, path);
-
- if (verbose>0)
- printf ("%s ==> ", command_line);
+ struct mount_entry *me;
+ struct fs_usage fsp;
+ char *disk;
- child_process = spopen (command_line);
- if (child_process == NULL) {
- printf ("Could not open pipe: %s\n", command_line);
- return STATE_UNKNOWN;
- }
+ mount_list = read_filesystem_list (0);
- child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
- if (child_stderr == NULL) {
- printf ("Could not open stderr for %s\n", command_line);
- }
+ if (process_arguments (argc, argv) != OK)
+ usage ("Could not parse arguments\n");
- while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
+ for (me = mount_list; me; me = me->me_next) {
- if (!index (input_buffer, '/'))
+ if ((dev_select_list &&
+ walk_name_list (dev_select_list, me->me_devname)) ||
+ (path_select_list &&
+ walk_name_list (path_select_list, me->me_mountdir)))
+ get_fs_usage (me->me_mountdir, me->me_devname, &fsp);
+ else if (dev_select_list || path_select_list)
continue;
-
- if (sscanf (input_buffer, "%s %d %d %d %d%% %s", file_system,
- &total_disk, &used_disk, &free_disk, &usp, mntp) == 6 ||
- sscanf (input_buffer, "%s %*s %d %d %d %d%% %s", file_system,
- &total_disk, &used_disk, &free_disk, &usp, mntp) == 6) {
-
- if (strcmp(exclude_device,file_system) == 0 ||
- strcmp(exclude_device,mntp) == 0) {
- if (verbose>0)
- printf ("ignoring %s.", file_system);
+ else if (fs_exclude_list && walk_name_list (fs_exclude_list, me->me_type))
+ continue;
+ else if (dp_exclude_list &&
+ walk_name_list (dp_exclude_list, me->me_devname) ||
+ walk_name_list (dp_exclude_list, me->me_mountdir))
+ continue;
+ else
+ get_fs_usage (me->me_mountdir, me->me_devname, &fsp);
+
+ if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) {
+ usp = (fsp.fsu_blocks - fsp.fsu_bavail) * 100 / fsp.fsu_blocks;
+ disk_result = check_disk (usp, fsp.fsu_bavail);
+ result = max_state (disk_result, result);
+ if (disk_result==STATE_OK && erronly && !verbose)
continue;
- }
-
- disk_result = check_disk (usp, free_disk);
-
- if (strcmp (file_system, "none") == 0)
- strncpy (file_system, mntp, MAX_INPUT_BUFFER-1);
if (disk_result!=STATE_OK || verbose>=0)
- asprintf (&output, "%s [%d kB (%d%%) free on %s]", output,
- free_disk, 100 - usp, display_mntp ? mntp : file_system);
-
- result = max_state (result, disk_result);
- }
-
- else {
- printf ("Unable to read output:\n%s\n%s\n", command_line, input_buffer);
- return result;
+ asprintf (&output, "%s [%llu MB (%2.0f%%) free on %s]",
+ output,
+ fsp.fsu_bavail*fsp.fsu_blocksize/1024/1024,
+ (double)fsp.fsu_bavail*100/fsp.fsu_blocks,
+ (!strcmp(file_system, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
+ asprintf (&details, "%s\n%llu of %llu MB (%2.0f%%) free on %s (type %s mounted on %s)",
+ details,
+ fsp.fsu_bavail*fsp.fsu_blocksize/1024/1024,
+ fsp.fsu_blocks*fsp.fsu_blocksize/1024/1024,
+ (double)fsp.fsu_bavail*100/fsp.fsu_blocks,
+ me->me_devname,
+ me->me_type,
+ me->me_mountdir);
}
}
- /* If we get anything on stderr, at least set warning */
- while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
- if (result != STATE_CRITICAL) {
- result = STATE_WARNING;
- }
- }
-
- /* close stderr */
- if (child_stderr)
- (void) fclose (child_stderr);
+ if (verbose > 2)
+ asprintf (&output, "%s%s", output, details);
- /* close the pipe */
- if (spclose(child_process)!=0 && result!=STATE_CRITICAL)
- result = STATE_WARNING;
+ terminate (result, "DISK %s%s\n", state_text (result), output, details);
+}
- if (usp < 0)
- printf ("Disk \"%s\" not mounted or nonexistant\n", path);
- else if (result == STATE_UNKNOWN)
- printf ("Unable to read output\n%s\n%s\n", command_line, input_buffer);
- else
- printf ("DISK %s%s\n", state_text (result), output);
- return result;
-}
+\f
/* process command-line arguments */
int
process_arguments (int argc, char **argv)
{
int c;
+ struct name_list *se;
+ struct name_list **pathtail = &path_select_list;
+ struct name_list **devtail = &dev_select_list;
+ struct name_list **fstail = &fs_exclude_list;
+ struct name_list **dptail = &dp_exclude_list;
-#ifdef HAVE_GETOPT_H
int option_index = 0;
static struct option long_options[] = {
{"warning", required_argument, 0, 'w'},
{"partition", required_argument, 0, 'p'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
+ {"errors-only", no_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"mountpoint", no_argument, 0, 'm'},
+ {"device", no_argument, 0, 'd'},
{"exclude_device", required_argument, 0, 'x'},
{"quiet", no_argument, 0, 'q'},
{0, 0, 0, 0}
};
-#endif
if (argc < 2)
return ERROR;
strcpy (argv[c], "-t");
while (1) {
-#ifdef HAVE_GETOPT_H
- c =
- getopt_long (argc, argv, "+?Vqhvt:c:w:p:x:m", long_options, &option_index);
-#else
- c = getopt (argc, argv, "+?Vqhvt:c:w:p:x:m");
-#endif
+ c = getopt_long (argc, argv, "+?Vqhvet:c:w:p:d:x:X:m", long_options, &option_index);
if (c == -1 || c == EOF)
break;
else {
usage ("Timeout Interval must be an integer!\n");
}
- case 'p': /* path or partition */
- path = optarg;
+ case 'p': /* selec path */
+ se = (struct name_list *) malloc (sizeof (struct name_list));
+ se->name = strdup (optarg);
+ se->name_next = NULL;
+ *pathtail = se;
+ pathtail = &se->name_next;
+ break;
+ case 'd': /* select partition/device */
+ se = (struct name_list *) malloc (sizeof (struct name_list));
+ se->name = strdup (optarg);
+ se->name_next = NULL;
+ *devtail = se;
+ devtail = &se->name_next;
+ break;
+ case 'x': /* exclude path or partition */
+ se = (struct name_list *) malloc (sizeof (struct name_list));
+ se->name = strdup (optarg);
+ se->name_next = NULL;
+ *dptail = se;
+ dptail = &se->name_next;
+ break;
+ break;
+ case 'X': /* exclude file system type */
+ se = (struct name_list *) malloc (sizeof (struct name_list));
+ se->name = strdup (optarg);
+ se->name_next = NULL;
+ *fstail = se;
+ fstail = &se->name_next;
break;
case 'v': /* verbose */
verbose++;
case 'q': /* verbose */
verbose--;
break;
+ case 'e':
+ erronly = TRUE;
+ break;
case 'm': /* display mountpoint */
display_mntp = TRUE;
break;
- case 'x': /* exclude path or partition */
- exclude_device = optarg;
- break;
case 'V': /* version */
- print_revision (PROGNAME, REVISION);
+ print_revision (progname, revision);
exit (STATE_OK);
case 'h': /* help */
print_help ();
return validate_arguments ();
}
+
+
int
validate_arguments ()
{
}
}
+
+
+\f
int
-check_disk (usp, free_disk)
+check_disk (int usp, int free_disk)
{
int result = STATE_UNKNOWN;
/* check the percent used space against thresholds */
return result;
}
+
+
+int
+walk_name_list (struct name_list *list, const char *name)
+{
+ while (list) {
+ if (! strcmp(list->name, name))
+ return TRUE;
+ list = list->name_next;
+ }
+ return FALSE;
+}
+
+
+
+\f
void
print_help (void)
{
- print_revision (PROGNAME, REVISION);
- printf
- ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
- "This plugin will check the percent of used disk space on a mounted\n"
- "file system and generate an alert if percentage is above one of the\n"
- "threshold values.\n\n");
+ print_revision (progname, revision);
+ printf ("Copyright (c) %s %s\n\t<%s>\n\n%s\n",
+ copyright, authors, email, summary);
print_usage ();
- printf
- ("\nOptions:\n"
- " -w, --warning=INTEGER\n"
- " Exit with WARNING status if less than INTEGER kilobytes of disk are free\n"
- " -w, --warning=PERCENT%%\n"
- " Exit with WARNING status if less than PERCENT of disk space is free\n"
- " -c, --critical=INTEGER\n"
- " Exit with CRITICAL status if less than INTEGER kilobytes of disk are free\n"
- " -c, --critical=PERCENT%%\n"
- " Exit with CRITCAL status if less than PERCENT of disk space is free\n"
- " -p, --path=PATH, --partition=PARTTION\n"
- " Path or partition (checks all mounted partitions if unspecified)\n"
- " -m, --mountpoint\n"
- " Display the mountpoint instead of the partition\n"
- " -x, --exclude_device=PATH\n"
- " Ignore device (only works if -p unspecified)\n"
- " -e, --errors-only\n"
- " Display only devices/mountpoints with errors\n"
- " -v, --verbose\n"
- " Show details for command-line debugging (do not use with nagios server)\n"
- " -h, --help\n"
- " Print detailed help screen\n"
- " -V, --version\n" " Print version information\n\n");
+ printf ("\nOptions:\n");
+ printf (options);
support ();
}
print_usage (void)
{
printf
- ("Usage: %s -w limit -c limit [-p path | -x device] [-t timeout] [-m] [-e] [--verbose]\n"
+ ("Usage: %s %s\n"
" %s (-h|--help)\n"
- " %s (-V|--version)\n", PROGNAME, PROGNAME, PROGNAME);
+ " %s (-V|--version)\n", progname, option_summary, progname, progname);
}