#!/usr/bin/perl -w
use strict;
use File::Find;
use File::stat;
use Getopt::Std;
use Sys::Hostname;
use Mail::Sendmail;
my %opts;
getopts('hd:p:s:t:rm',\%opts);
usage() if ( $opts{h} || ( !$opts{d} ) );
my ($directory) = ("")x1;
if ($opts{d}) { $directory = $opts{'d'}; }
if ($opts{r}) { report(); }
if ($opts{m}) { mail(); }
my @dirList = "";
my @users = "";
my $summary = "";
my $host = hostname;
sub usage
{
print "Usage:\n\n";
print "\t dirmonitor -d <dir>";
}
sub report
{
my ($owner,@fileList,%HoA_Sizes,%HoA_Dirs,@tokens,$user,$file,$dir,$size,$cat,$sum);
print "Inspecting directory: $directory ...\n\n";
# ignore any duplicate files and directories but to proceed normally otherwise
find( {wanted => \&wanted, follow_skip => 2 }, $directory);
# Create a hash of arrays with our newly found directories, each array in the
# hash contains directories that the user owns. Each array is keyed by the
# owners user name.
foreach (@dirList) {
$dir = $_;
$user = getpwuid(stat($dir)->uid);
$size = -s $dir;
# test if we have an undefined user or not
if (defined $user) {
push @{$HoA_Sizes{$user}}, $size;
push @{$HoA_Dirs{$user}}, $dir;
}
}
# grab list of users
@users = keys %HoA_Sizes;
# sum up the sizes of directories that the user owns
foreach $owner ( @users ) {
my %dirHash;
# dereference the array reference and grab the list of values
my @ownersDirSizes = @{ $HoA_Sizes{$owner} };
my @ownersDirs = @{ $HoA_Dirs{$owner} };
@dirHash{ @ownersDirs } = @ownersDirSizes;
foreach my $toke ( keys %dirHash ) {
$sum += $dirHash{$toke};
}
push @{$HoA_Sizes{$owner}}, $sum;
$sum = 0;
@ownersDirSizes = "";
@ownersDirs = "";
}
# sort the hash of arrays by comparing the first value of a users
# array(sum of all users dirs)
foreach $owner ( sort { $HoA_Sizes{$b}->[-1] <=> $HoA_Sizes{$a}->[-1] } keys %HoA_Sizes ) {
$summary .= sprintf "%-12s %2.2f GB\n", $owner, @{[$HoA_Sizes{$owner}->[-1]/1000000000]};
}
print "$summary\n";
#mail();
}
sub wanted {
# if file exists
if (-e $_) {
if ($_ ne ".") {
push(@dirList,$File::Find::name);
}
}
sub mail {
foreach my $user (@users) {
print "recipient is: $user\n";
my %message = ( To => $user,
From => 'root@localhost',
Subject => 'Disk usage summary',
Message => $summary
);
sendmail(%message) or die $Mail::Sendmail::error;
}
print "Log says: \n", $Mail::Sendmail::log;
}