[comp.lang.perl] perl Bnews expire script

eay@surf.sics.bu.oz (Eric the Young) (08/27/90)

A few weeks ago I wrote a perl script to intelligently expire news on
our news partition.  After asking around locally I found that
most people have their news setup to expire news after a fixed number
of days as opposed to running expire every time the news partition
had less than x meg. free on it.  Feeling that other people may be able to
use this script I now post it.
If I have just reinvented the wheel, break it to me gently

If you have no interest in this, hit 'n' now.

Background.
Our site has a dedicated 120 meg. /usr/spool/news on a microvax 3600
running ultrix 3.0.  The partitions has a very
large number of inodes and has the 'min free disk %' set to zero
(read tunefs under the -m option).  I have my script run from cron
every few hours with parameters set so that every time
there is less than 20 meg. free, it runs expire so that
there will be a least 30 meg. free when expire has finished.
What this means is that the disk will normally all ways have about
20 meg. free (less if lots of news comes in a space of a few hours)
and will remove news only when it needs to.  Since there should
never normally be under 10 meg. free, the disk degradation that would occur
at this point (due to 0% free disk) should not occur.

If anyone finds this useful, please give me some feed back
(this is my first software post, I need encouragement :-) :-)

--8<--8<--
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  expiredisk.perl
# Wrapped by eay@surf on Mon Aug 27 17:20:04 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'expiredisk.perl' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'expiredisk.perl'\"
else
echo shar: Extracting \"'expiredisk.perl'\" \(2789 characters\)
sed "s/^X//" >'expiredisk.perl' <<'END_OF_FILE'
X#!/usr/local/bin/perl
X#
X# expiretime v 1.1 Eric Young (eay@surf.bu.oz.au)
X#
X# This scipt is used to manage free disk space on our news partition.
X#
X# On our host we have a dedicated /usr/spool/news with a very high
X# number of inodes and a minimun disk free space of 0%.
X# This script, which is run every 2 hours, calculates the corect parameters
X# to pass to expire so that expire will be run quite infrequently.
X# 
X# 1) use df to see if we need to run expire
X# 2) if yes; addup how much news there is for each day
X# 3) run expire once with the correct parameters to delete just enough
X#    news.
X#
X# It is run on our system as
X# expiretime 20000 30000
X#
X# v 1.0 11/07/90
X#
X$NEWSDIR='/usr/spool/news';
X
X($#ARGV == 1) || die "expiretime <min-free> <free upto>\n";
open(LOG,">>/usr/adm/expiretime.log") || die "unable to open log file:%!";
X
select(LOG); $|=1;
X$minfree=$ARGV[0];
X$keepfree=$ARGV[1];
X
X$free=&fsfree($NEWSDIR);
X
X$maxage=0;
X@size_bytes=();
X@numfiles=();
X
X$now=time();
X($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($now);
X$nowday=$yday+($year*365);
X
printf(LOG "%02d:%02d - %2d/%02d/%02d: ",$hour,$min,$mday,$mon+1,$year);
printf(LOG "Free: %d  KeepFree: %d",$free,$minfree);
if ($free > $minfree)
X	{
X	printf(LOG "  No expire needed\n");
X	exit 0;
X	}
else
X	{
X	printf(LOG "  Doing expire\n");
X	}
X
chdir($NEWSDIR);
X&dodir();
X
X$maxage=1000 if ($maxage > 1000);	# just in case
for ($i=0; $i <= $maxage; $i++)
X	{
X	if ($numfiles[$i] > 0)
X		{
X		printf(LOG "day %2d  num=%5d size_l=%10d\n",$i,
X			$numfiles[$i],$size_bytes[$i]/1024);
X		}
X	}
X
X$days=$maxage;
X$totfree=0;
for ($i=$maxage; $i >= 0; $i--)
X	{
X	$days=$i;
X	$totfree+=($size_bytes[$i]/1024);
X	last unless ($totfree+$free < ($keepfree));
X	}
X
X$hist=$days+14;
printf(LOG "/usr/lib/news/expire -i -e $days -E $hist\n");
if ($days >= 1)
X	{
X	exec("/usr/lib/news/expire -i -e $days -E $hist");
X	}
X
sub dodir
X	{
X	opendir(DIR,'.') || die "Can't open dir";
X	local(@filenames) = readdir(DIR);
X	closedir(DIR);
X
X	for (@filenames)
X		{
X		next if $_ eq '.';
X		next if $_ eq '..';
X
X		($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,
X		$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($_);
X		($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=
X			localtime($mtime);
X		if ($mode & 0040000) # a dir
X			{
X			chdir $_ || die "Can't cd to $_";
X
X			&dodir();
X			chdir('..');
X			}
X		else
X			{
X			$age=$nowday-($yday+($year*365));
X			if ($age > $maxage)
X				{
X				$maxage=$age;
X				$#size_bytes=$[+$maxage;
X				$#numfiles=$[+$maxage;
X				}
X
X			$size_bytes[$age]+=$size;
X			$numfiles[$age]++;
X			}
X		}
X	}
X
sub fsfree
X	{
X	local($fs)=@_;
X
X	open(FS,"/bin/df $fs|") || die "Unable to run df\n";
X	for (<FS>)
X		{
X		chop;
X		split;
X		if ($_[0] =~ "dev")
X			{
X			close(FS);
X			return($_[3]);
X			}
X		}
X	die "unable to find disk usage for $fs\n";
X	}
X
END_OF_FILE
if test 2789 -ne `wc -c <'expiredisk.perl'`; then
    echo shar: \"'expiredisk.perl'\" unpacked with wrong size!
fi
chmod +x 'expiredisk.perl'
# end of 'expiredisk.perl'
fi
echo shar: End of shell archive.
exit 0
-- 
Eric Young                       | "It is always best to start running
System Programmer, SICS Bond Uni.| away early, before the rush.  That way
ACSnet: eay@surf.sics.bu.oz.au   | there are fewer bodies to trip over."