[hypermail] Monthly rotation

From: Scott Rose <srose_at_direct.ca_at_hypermail-project.org>
Date: Tue, 20 Feb 2001 13:01:42 -0800
Message-ID: <3A92DB35.8BC6E9F2_at_direct.ca>

Just to join into the general festival of monthly-rotation approaches, I offer the following script. In my approach, I leave the command line for hypermail alone, but manipulate a symlink to its destination directory. This script- run under cron just after the end of a cyclealso  creates the new target directory (and optionally prunes old ones so as to maintain the desired depth). I name the directories <listname>_MMYY for monthly rotation, but that's configurable on the command line. A command line for monthly rotation is

  5 0 1 * * /<path to script>/new_hype.pl -v -b <name> -d <directory>

which runs at 00:05 on the first day of each month, and uses the default naming scheme. hypermail writes to the directory with the basename of the list, which is the name of the symlink.

On an entirely different note, I have code that improves the performance of hypermail, particularly in the case of large archives- hypermail opens each file in an archive to build new indices each time a message arrives when you run in message-at-a-time mode, and it's desperately expensive. My approach uses a GDBM index so that a whole lot less I/O has to take place. I've been waiting for 2.0 to ship before bringing this up again... I mentioned it to Kent a year or so ago. Any interest? It should be generalized beyond GDBM to be most widely useful...

BTW, is one mailing list enough for this project? Using the same list for coordinating development, fielding bug reports, and providing user support means that I am often loathe to post.

# rotate_hype.pl

# Concept:

# Put in a crontab, this script will "rotate" a hypermail
# archive. That means creating a new one, possibly renaming old
# ones, and possibly deleting one. It does nothing with mail
# aliases, nothing with the hypermail targets: it simply creates,
# renames, and deletes directories.

# Options:

# -d <dir> this names the directory where the archives
are to
# be created
# -n <count> how deep do we allow the archives to get
before we
# start deleting?
# -t <naming template> this describes how to name the archive

use Getopt::Std;
use strict 'vars';
use vars qw($opt_d $opt_t $opt_n $opt_v);


my $template = 'hype_%d';
$template = $opt_t if(defined $opt_t);
my $dirRoot;
my _at_these;
if(defined $opt_d) {

    $dirRoot = $opt_d;
} else {

    die "$0: -d must be specified\n";
$dirRoot =~ s^/$^^; # lose a trailing '/' die "\"$dirRoot\" does not exist and I won't create it." unless(-d $dirRoot);
my $depth = 1;
$depth = $opt_n if(defined $opt_n);
my $verbose = $opt_v;
print "Building archives in \"$dirRoot\" to a depth of $depth using naming templ
ate \"$template\".\n" if($verbose);

# Build the filenames and determine what already exists.

my $i;
for $i (1..$depth) {

    push _at_these, {};
    $these[$i-1]->{name} = sprintf $template, $i;     $these[$i-1]->{'exists'} = (-d "$dirRoot/$these[$i-1]->{name}");

    print "\"$dirRoot/$these[$i-1]->{name}\" ",
      $these[$i-1]->{'exists'} ? 'exists' : 'does not exist', "\n"


if($these[$depth-1]->{'exists'}) {

    `/bin/rm -r $dirRoot/$these[$depth-1]->{name}`;     if(-d "$dirRoot/$these[$depth-1]->{name}") {

        die "Failed to remove \"$dirRoot/$these[$depth-1]->{name}\", bailing";

    } else {

        print "Removed \"$dirRoot/$these[$depth-1]->{name}\"\n" if($verbose);


# Move each archive we plan to keep to the next name up.

for($i = $depth-1; $i; $i--) {

    if($these[$i-1]->{'exists'}) {

        `/bin/mv $dirRoot/$these[$i-1]->{name} $dirRoot/$these[$i]->{name}`;

        die "Failed to move \"$dirRoot/$these[$i-1]->{name}\" to $dirRoot/$these
[$i]->{name}\"; bailing"

            unless((-d "$dirRoot/$these[$i]->{name}") &&
                   !(-d "$dirRoot/$these[$i-1]->{name}"));
        print "Moved \"$dirRoot/$these[$i-1]->{name}\" to
>{name}\"\n" if($verbose);


# Make the new guy.

`/bin/mkdir $dirRoot/$these[0]->{name}`; die "Failed to create \"$dirRoot/$these[0]->{name}\", bailing"

    unless(-d "$dirRoot/$these[0]->{name}"); print "Created \"$dirRoot/$these[0]->{name}\"\n" if($verbose); Received on Tue 20 Feb 2001 11:11:30 PM GMT

This archive was generated by hypermail 2.3.0 : Sat 13 Mar 2010 03:46:12 AM GMT GMT