Cover V08, I08
Article
Listing 1
Table 1

aug99.tar


Listing 1: dcp

dcp--disk capacity profiler, source code

#!/usr/local/bin/perl

# dcp - disk capacity profiler
# (c) 1999 inkcom

# Modify df command to fit your path and version
$dfcommand = "/bin/df -k";
# The file containing historical data
$history = ".dcp";

# Make sure that one or more filesystems are specified on the command-line
$usage = "Usage: $0 filesystem [filesystems...]\n";
if (@ARGV < 1) {
   print $usage;
   exit;
}

# Open the history file for writing, if possible
open HISTORY, ">> $history" or die "Cannot open $history for writing";

foreach $filesystem (@ARGV) {
   # Make sure the filesystem exists
   if (! -e $filesystem) {
      print STDERR "$filesystem does not exist\n";
      next;
   }

   # Create a list of requested filesystems, for later use
   @filesystems = (@filesystems, $filesystem);

   # Get the df statistics
   $filesystem_info = `$dfcommand $filesystem`;

   # Get rid of the header line
   $filesystem_info =~ s/(.)+\n//;

   # Get the total, used and available space values
   # We are expecting the following format for the output of df:
   # Filesystem         kbytes   used   avail capacity  Mounted on
   # /dev/dsk/c0t3d0s0   192807   19980  153547    12%    /
   ($discard, $total, $used, $available, @discard) = split /\s+/, $filesystem_info;

   # Get the timestamp
   $time = time;

   # Save the data into the history file
   print HISTORY "$time;$filesystem $total $used $available\n";
}

# Close the history file for writing
close HISTORY;

# Open the history file again for reading, or complain
open HISTORY, "$history" or die "Cannot open $history for reading\n";

# Read the history into assiciative arrays
while (<HISTORY>) {
   ($timefilesystem, $total, $used, $available) = split /\s+/, $_;
   $total{$timefilesystem} = $total;
   $used{$timefilesystem} = $used;
   $available{$timefilesystem} = $available;
}

# Do some preliminary calculations
foreach $timefilesystem (sort keys %total) {
   ($time, $filesystem) = split /;/, $timefilesystem;
   foreach $fs (@filesystems) {
      if ($filesystem eq $fs) {
         if (!$prevtime{$fs}) {
            $prevtime{$fs} = $time;
            $prevused{$fs} = $used{$timefilesystem};
            next;
         }

         # Time difference between data points
         $timediff = $time - $prevtime{$fs};

         # Just in case...
         next if ($timediff == 0);

         # Calculate the size growth rate in seconds
         $growthrate = ($used{$timefilesystem} - $prevused{$fs})/$timediff;
         
         # Save these numbers for the average calculation
         $growthratetotal{$fs} = $growthratetotal{$fs} + $growthrate;
         $growthratenumber{$fs}++;
         $lastsize{$fs} = $available{$timefilesystem};

         # Save the time and used values for next round
         $prevtime{$fs} = $time;
         $prevused{$fs} = $used{$timefilesystem};
      }
   }
}

# Print out the results
foreach $fs (@filesystems) {
   # If there is not enough data, i.e., it's the first time that 
   # info is requested for a particular partition
   if ($growthratenumber{$fs} == 0 ) {
      print "Not enough data for $fs. Please run $0 again.\n";
      next;
   }

   # Calculate the average time left in hours and days
   $growthrate = $growthratetotal{$fs}/$growthratenumber{$fs};

   # Growthrate must be non-zero
   if ($growthrate != 0) {
      # Calculate the time left at the present in days and hours
      $timeleft = $lastsize{$fs}/$growthrate/3600;
      $daysleft = $timeleft/24;

      # If the partition is filling up...
      if ($timeleft > 0 ) {
         printf "$fs will be FULL in about %.2f hours (%.2f days)\n", $timeleft, $daysleft;
      # Or, if the partion is emptying...
      } else {
         printf "$fs will be EMPTY in about %.2f hours (%.2f days)\n", abs $timeleft, abs $daysleft;
      }
   # Otherwise, there is no growth
   } else {
      print "$fs is not changing in size\n";
   }
}