#!/usr/bin/perl # # diskwarn - mail warnings about filesystems that are getting too full # $Id: diskwarn,v 3.0 2003/04/16 19:20:12 cos Exp cos $ # # diskwarn mails out warnings about local filesystems with high usage. # Run this from crontab at a frequency of your choosing. When a # warning is mailed about a filesystem, that filesystem's state is # written in /etc/diskwarn.cache, and no more warnings will be sent # out for that filesystem until its usage changes again (or # diskwarn.cache is deleted). # # The two important configurable parameters are threshold and mail. # Either of these can be set on the command line (i.e. "diskwarn # mail=ops") or by changing the default value here in the script. # threshold is the percentage usage at which point a filesystem is # considered to be full enough to warrant a warning. mail is the # address(es) to mail the warnings to. # # If you want some filesystems to be ignored, or want to configure a # per-filesystem warning threshold, list those filesystems, in the # file /etc/diskwarn.exclude. Name one filesystem per line. If a # filesystem name appears on a line by itself, that filesystem will # always be skipped and you'll never get warnings about it. If there # is a number after the filesystem name, separated by whitespace, then # that number will be used as the percentage threshold. For example: # # /usr # /var 80 # # Never send warnings about /usr, and warn about /var if it's over 80%, # regardless of what the general threshold parameter is set to. # You can add a % sign and a comma for readbility, like this: /var, 80% # # This script is distributed under the terms of Larry Wall's # excellent Artistic License. If you have bug fixes or enhancements, # email cos@aaaaa.org. For a copy of the Artistic License, see: # http://language.perl.com/misc/Artistic.html # # (C)opyright 1996-2003 Ofer Inbar require 5; my %exclude = (); # these can't be my variables for the command line argument processing to work $threshold = "93"; $mail="cos"; $mailer="/usr/lib/sendmail -oi"; $exclude="/etc/diskwarn.exclude"; $cache="/etc/diskwarn.cache"; $df = 'default'; chomp(my $uname = `uname -sr`); chomp(my $host = `hostname`); my $me = getpwuid($>); if ($uname =~ /^SunOS 4/) { $df = "df -t 4.2" } elsif ($uname =~ /^SunOS 5/) { $df = "df -k -F ufs" } elsif ($uname =~ /^HP-UX A.09/) { $df = "bdf -t hfs" } elsif ($uname =~ /^HP-UX A.10/) { $df = "bdf -l" } elsif ($uname =~ /^AIX/) { $df = "df -k --type=jfs" } elsif ($uname =~ /^IRIX/) { $df = "df -lk" } elsif ($uname =~ /^Linux/) { $df = "df -x nfs -x afs" } elsif ($uname =~ /^FreeBSD 2/) { $df = "df -k -t local" } elsif ($uname =~ /^FreeBSD/) { $df = "df -k -t noprocfs,cd9660,nfs,mfs" } eval "warn \$die='Unknown switch $1\n' if \$$1 eq ''; \$$1=\$2;" while ($ARGV[0] =~ /^(\w+)=(.*)/ && shift); exit 1 if $die; # process any FOO=bar switches die "I don't know your OS '$uname', you must supply a df command.\n" if $df eq 'default'; if (-f $exclude) { open EXCLUDE, "< $exclude" or warn "$0: can't read $exclude: $!\n"; while () { next unless /\S/; # don't print warnings about blank lines my ($part,$thresh) = /^(\/[\w\d\/]*),?\s*(\d+)?/; unless ($part) { warn "$0: bad line in $exclude:\n$_\n"; next } $exclude{$part} = $thresh || 200; # arbitrary number higher than df will ever report } close EXCLUDE; } if (-f $cache) { open CACHE, "< $cache" or warn "$0: can't read $cache: $!\n"; while () { ($filesys,$avail) = /^([^\t]+)\t(\d+)/; $cache{$filesys} = $avail; } close CACHE } open CACHE, "> $cache" or warn "$0: can't write $cache: $n"; open DF, "$df |" or die "$0: can't run $df : $!\n"; while () { next unless my ($kbytes,$used,$avail,$capacity,$filesys) = /^\/\S+\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)%\s+(\S+)/; # set threshold to a local value that may be filesys-specific my $threshold = $exclude{$filesys} || $threshold; next if $capacity < $threshold; print CACHE "$filesys\t$avail\n"; next if $avail == $cache{$filesys}; if ($mail) { if (open MAIL, "| $mailer $mail") { select MAIL } else { warn "$0: can't pipe to $mailer: $!\n" } } print < To: $mail Subject: WARNING: $host:$filesys at ${capacity}% (${avail}K free) This warning was generated by $0 running on $host, using the command: $df The threshold for warnings is ${threshold}% If you want to exclude this filesystem from being checked by the warning script, list its name (mount point) in $exclude WARNINGMAIL close MAIL; } close DF, CACHE;