#!/usr/bin/perl -w
# check_disk_space.pl
# Send an email notice out when mounted file systems are past a given
+percentage.
#
# Perl v5.8.8
# Tested under RHEL4, RHEL5, and RHEL6
#
# When this script is run it will check the status of all mounted file
+ systems
# using the df command and if the percentage is past the given critica
+l set level
# will send out an email notice every time it is run. A set warning pe
+rcentage
# only send out an email every number_of_days_before_next_warning.
# It keeps track of the number_of_days_before_next_warning using lock
+files.
#
# The check_disk_space.xml config file should be in the same directory
+ as the program,
# and be given the same name if the program name is changed.
#
#check_disk_space.xml
# < = <, > = >
#-
# <config>
# <warning_percent_used>90</warning_percent_used>
# <critical_percent_used>99</critical_percent_used>
# <number_of_days_before_next_warning>7</number_of_days_before_next_w
+arning>
# <warning_lock_directory>/home/<user>/</warning_lock_directory>
# <hide_warning_lockfile>yes</hide_warning_lockfile>
# <Include_Hostname_In_Subject>no</Include_Hostname_In_Subject>
# <command_df>/bin/df</command_df>
# <command_find>/bin/find</command_find>
# <command_rm>/bin/rm</command_rm>
# <command_date>/bin/date</command_date>
# <command_hostname>/bin/hostname</command_hostname>
# <command_sendmail>/usr/sbin/sendmail</command_sendmail>
# <mail_to>user@mail.com</mail_to>
# <mail_from>Disk Check <user@system.com></mail_from>
# <mail_subject_prefix>Disk Check</mail_subject_prefix>
# <mail_subject_postfix></mail_subject_postfix>
# <mail_x_mailer>Disk Check</mail_x_mailer>
# </config>
#-
#
# The following config toggles whether the host appears in the subjec
+t line.
# A value of "yes" will trigger the hostname include.
# <Include_Hostname_In_Subject>no</Include_Hostname_In_Subject>
#
# The following line troggles weather or not lock files are created wi
+th a
# hidden dot prefix. A value of "yes" will trigger the hidden file.
# <hide_warning_lockfile>yes</hide_warning_lockfile>
#
# The following line determins where the lock files will be placed. If
+ left
# blank the lock files will be saved in the current directory. Be sure
+ to
# end a directory path with a "/" in the config file.
#<warning_lock_directory>/home/<user>/</warning_lock_directory>
#
# This program doesn't require any special privlege accesses, except r
+ead/write
# access to the lockfile directory.
#
# Recommended Crontab Entry:
# # Check precentage of disk used every day and send out a email if cr
+itical levels are reached.
# 0 7 * * * cd /home/<user>/bin; /home/<user>/bin/check_disk_space.pl
#
# Script requirements: install XML Simple
# yum install perl-XML-Simple
#
# History:
# --------------------------------------------------------------------
+-------
# 2014-02-24 kienenbe Started, works.
#
use XML::Simple;
use File::Basename;
#use Data::Dumper;
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Get the mount points from the df command.
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sub get_filesystem_data {
my @mount_points;
my $df_line;
my $filesystem;
my $junk;
my $total_size;
my $amount_used;
my $amount_avalible;
my $percent_used;
my @df_output = `$command_df -lh`;
foreach $df_line (@df_output) {
if ($df_line =~ m#\d\%#) {
#print "->$df_line";
# Break out the needed data.
($percent_used,$filesystem) = split(/% /, $df_line);
chomp $filesystem;
($junk,$total_size,$amount_used,$amount_avalible,$percent_used)
+= split(/\s+/, $percent_used);
# Record the data for the filesystem mount point.
$filesystem_info{"$filesystem"}{"total_size"} = "$total_size";
$filesystem_info{"$filesystem"}{"amount_used"} = "$amount_used";
$filesystem_info{"$filesystem"}{"amount_avalible"} = "$amount_av
+alible";
$filesystem_info{"$filesystem"}{"percent_used"} = "$percent_used
+";
}
}
}
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Format the text report output for display.
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# system.mysystem.org
# Fri Feb 21 13:47:03 UTC 2014
#
# ---- Critical file system space at or above 45% ----
#
# Size Used Avail Use% Mounted on
+
# 1.8T 769G 973G 45% /mnt/backup
+
# 1.1T 436G 550G 45% /data
+
#
# ---- Warning file system space at or above 8% ----
#
# Size Used Avail Use% Mounted on
+
# 485M 38M 422M 9% /boot
sub format_report_output {
$warning_duplicate_check = 0;
$critical_duplicate_check = 0;
my $filename;
# Cycle though each filesystem mount point.
foreach my $filesystem (keys %filesystem_info) {
if ($filesystem_info{"$filesystem"}{"percent_used"} >= $critical_p
+ercent_used) {
if ($critical_duplicate_check eq 0) {
# Only print the date and time stamp if this is the first wa
+rning check.
if ($warning_duplicate_check eq 0) {
$formated_report .= "\n $Hostname\n $TimeStamp\n
+";
}
$formated_report .= "\n ---- Critical file system space at or
+above ${critical_percent_used}% ----\n\n";
$formated_report .= sprintf(" %5s %5s %5s %5s %-60s\n", "S
+ize","Used","Avail","Use%","Mounted on");
$critical_duplicate_check = 1;
}
$formated_report .= sprintf(" %5s %5s %5s %5s %-60s\n", $fil
+esystem_info{$filesystem}{total_size},$filesystem_info{$filesystem}{a
+mount_used},$filesystem_info{$filesystem}{amount_avalible},"$filesyst
+em_info{$filesystem}{percent_used}%",$filesystem);
}
elsif ($filesystem_info{"$filesystem"}{"percent_used"} >= $warning
+_percent_used) {
# Concert the file system mount point to a file name.
$filename = &convert_filesystem_path_to_name($filesystem);
# Remove warning locks for file system mount points past the num
+ber_of_days_before_next_warning
&remove_warning_lockfile($filename);
if (&check_for_warning_lockfile($filename)) {
# Do nothing
}
else {
if ($warning_duplicate_check eq 0) {
# Only print the date and time stamp if this is the first cr
+itical check.
if ($critical_duplicate_check eq 0) {
$formated_report .= "\n $Hostname\n $TimeStamp\n
+";
}
$formated_report .= "\n ---- Warning file system space at or
+ above ${warning_percent_used}% ----\n\n";
$formated_report .= sprintf(" %5s %5s %5s %5s %-60s\n",
+"Size","Used","Avail","Use%","Mounted on");
$warning_duplicate_check = 1;
}
$formated_report .= sprintf(" %5s %5s %5s %5s %-60s\n", $f
+ilesystem_info{$filesystem}{total_size},$filesystem_info{$filesystem}
+{amount_used},$filesystem_info{$filesystem}{amount_avalible},"$filesy
+stem_info{$filesystem}{percent_used}%",$filesystem);
# Create a warning lock file for the current file system mount
+ point.
&write_warning_lockfile($filename);
}
}
}
}
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Send out the email to the recipients.
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sub send_email_notice {
# Send full report to recepiants(s)
# Remove complaint about global empty vars such as ${mail_subject_po
+stfix}
no warnings 'uninitialized';
if ( $warning_duplicate_check eq 1 or $critical_duplicate_check eq
+1) {
open (MAIL, "|$command_sendmail -t") || die "Can't open the mail b
+inary: ${command_sendmail}!\n";
print MAIL "X-Mailer: ${mail_x_mailer}\n";
print MAIL "Return-Path: root\@${Hostname}\n";
print MAIL "From: ${mail_from} <root\@${Hostname}>\n";
print MAIL "To: ${mail_to}\n";
if ($Include_Hostname_In_Subject eq "yes") {
print MAIL "Subject: ${mail_subject_prefix}${Hostname}${mail_sub
+ject_postfix}\n\n";
}
else {
print MAIL "Subject: ${mail_subject_prefix}${mail_subject_postfi
+x}\n\n";
}
print MAIL "\n${formated_report}\n\n";
close (MAIL);
}
}
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Conver the file system mount point to a lockfile name.
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sub convert_filesystem_path_to_name {
my $filesystem_path = shift;
my $lockfile_name;
$filesystem_path =~ s#/#_#g;
$filesystem_path =~ s# #_#g;
if ($hide_warning_lockfile eq "yes") {
$lockfile_name = "." . $program_name . "_warning_lock" . $filesyst
+em_path;
}
else {
$lockfile_name = $program_name . "_warning_lock" . $filesystem_pat
+h;
}
return ($lockfile_name);
}
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Save the warning lockfile
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Creates the locking file in the format of:
# / are converted to underscores for mount point.
# <.><progran name><_warning_lock><mountpoint>
#
# -rwxr-x---. 1 user user 9211 Feb 21 13:46 df.pl*
# -rw-rw-r--. 1 user user 0 Feb 21 13:47 .df_warning_lock_boot
sub write_warning_lockfile {
my $lockfile_name = shift;
my $lockfile_directory = "./";
# Check if the $warning_lock_directory has been set.
# If so use it instead of the current directory.
if ( $warning_lock_directory) {
$lockfile_directory = $warning_lock_directory;
}
# Check for the warning lockfile.
# If it already exists exit.
if ( -e "${lockfile_directory}${lockfile_name}" ) {
return;
}
open (WARNING_LOCKFILE, '>', ${lockfile_directory}.${lockfile_name})
+ or $formated_report .= "\nUnable to save warning lockfile for ${lock
+file_directory}${lockfile_name}\n Warnings will be sent out every tim
+e the script runs.\n\n";
close (WARNING_LOCKFILE);
}
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Check for the warning lockfile
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sub check_for_warning_lockfile {
my $lockfile_name = shift;
my $lockfile_directory = "./";
# Check if the $warning_lock_directory has been set.
# If so use it instead of the current directory.
if ( $warning_lock_directory) {
$lockfile_directory = $warning_lock_directory;
}
# Check for the warning lockfile.
if ( -e "${lockfile_directory}${lockfile_name}" ) {
return 1;
}
else {
return 0;
}
}
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Remove the warning lockfile
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sub remove_warning_lockfile {
my $lockfile_name = shift;
my $lockfile_directory = "./";
# Check if the $warning_lock_directory has been set.
# If so use it instead of the current directory.
if ( $warning_lock_directory) {
$lockfile_directory = $warning_lock_directory;
}
# If the file doesn't exist just exit.
if (! -e "${lockfile_directory}${lockfile_name}" ) {
return;
}
# Remove the warning lockfile.
`$command_find ${lockfile_directory}${lockfile_name} -mtime +${numbe
+r_of_days_before_next_warning} -type f -exec $command_rm -f {} \\;`;
}
# Run the main routine.
&Start;
#>>>>>>>>>>>>>
#> Main Start
#>>>>>>>>>>>>>
sub Start {
#declare all major variables used in this subroutine.
local (%filesystem_info, $TimeStamp, $Hostname, $formated_report, $w
+arning_duplicate_check, $critical_duplicate_check, $program_name);
# Obtain configuration from a file with a name inferred from this
# script's name.
($program_name) = split(/\./, basename($0));
my $program_full_name =basename($0);
# if you don not wish to use XML::Simple comment out next line..
$config = XMLin("${program_name}.xml", SuppressEmpty => 'undef');
# if you don not wish to use XML::Simple configure variable directly
+ here.
# if you don't use the XML config file you must place a "\" in front
+ of the
# "@" in your email address so it is not interpreted as an array var
+iable.
# ex: local $mail_to = "vadapt.notice\@gm
+ail.com";
local $command_date = $config->{'command_date'
+};
local $command_df = $config->{'command_df'};
local $command_find = $config->{'command_find'
+};
local $command_hostname = $config->{'command_hostn
+ame'};
local $command_rm = $config->{'command_rm'};
local $command_sendmail = $config->{'command_sendm
+ail'};
local $warning_percent_used = $config->{'warning_perce
+nt_used'};
local $critical_percent_used = $config->{'critical_perc
+ent_used'};
local $number_of_days_before_next_warning = $config->{'number_of_day
+s_before_next_warning'};
local $warning_lock_directory = $config->{'warning_lock_
+directory'};
local $hide_warning_lockfile = $config->{'hide_warning_
+lockfile'};
local $Include_Hostname_In_Subject = $config->{'Include_Hostn
+ame_In_Subject'};
local $mail_to = $config->{'mail_to'};
local $mail_from = $config->{'mail_from'};
local $mail_subject_prefix = $config->{'mail_subject_
+prefix'};
local $mail_subject_postfix = $config->{'mail_subject_
+postfix'};
local $mail_x_mailer = $config->{'mail_x_mailer
+'};
# Get the hostname
local $Hostname = `$command_hostname -f`;
chomp $Hostname;
# Get the date timestamp
$TimeStamp = `$command_date`;
chomp $TimeStamp;
# Do the work
&get_filesystem_data;
&format_report_output;
&send_email_notice;
# uncomment to print report when run.
#print $formated_report;
#End the program
exit;
}
|