Bourne, BSD utilities, and backups, or: How I learned to stop worrying, and love the epoch.

I know it's been forever since I've written anything; I've moved on to 'Real Life' - and it's been a wonderful replacement.

I write this merely as a useful hint to folks who might have a use for this. Several of my new projects are colocated on another system, of which I do not have root access, and do not want to localize installation of GNU utilities, only to have them. One of these being GNU date.

GNU date is much easier to use than BSD date, because, say, if I wanted now - but the month and day of exactly a week ago, I could just say:

date --day="seven days ago" " +%Y.%m.%d"

Not so in BSD. BSD's command line DATE utility will output the time in several formats - one of them being the epoch (%s), but will not allow you to feed it the date in this format, so, for my purposes, it's useless.

I ended up making this throwaway little perl script, which I call *lastweek.pl* (Originally I localized my $time with ARGV[0] to feed it the epoch and have it spit out the date, but honestly, I have no need for that, and this will make things just a touch faster in a few million years of use.)

#!/usr/bin/perl
use warnings;
use strict;
my ($sec, $min, $hour, $day, $month, $year, $wday, $yday, $isdst) = localtime(time() - 604800); # 604800 is 7 days in seconds.
$year += 1900;
$month += 1;
printf("%04d.%02d.%02d\n", $year, $month, $day);


What this script does is print out the year.month.day, in the same format which I store the local date (today) in my shell script. Today's date is obtained:

TODAY=`date +%Y.%m.%d`

So, to use this:

LASTWEEK=`/usr/bin/perl $HOME/bin/lastweek.pl`

Now, for the (horrible, horrible) script. Many of these things aren't commented, because they're a waste of resources (using 'tr' to print the domain in uppercase, an abuse of pipes, etc). However, my goal was to make a script that will work anywhere that has tar, gzip and the most basic system tools. (Perl is a requirement for the old file removal process, but virtually all systems have Perl 5 by now):

#!/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin:/sbin
DESTDIR=$HOME/backup
FAILED=`false`
DATE=`date +%Y.%m.%d`
LASTWEEK=`/usr/bin/perl $HOME/bin/lastweek.pl`
SITES=`for n in $HOME/hosted/www.*.com; do echo $n; done` #Dumb, but gives us a space delimited array, no globbing required, and no thrashing with find.
echo "Backing up hosted sites on $DATE, "`date +%H:%M`"."
echo ""
for HOST in $SITES; do
  DOMAIN=`basename $HOST | sed s,'www.','',g`
  echo -n '>> '`echo $DOMAIN | tr '[a-z]' '[A-Z]'`': '
  tar cPf - $HOST : gzip -9 > "$DESTDIR/$DOMAIN-$DATE.tar.gz"
  if [ $? != 0 ]; then
    echo "FAILED!"
    FAILED=`true`
  else
    echo -n "done."
    if [ -f "$DESTDIR/$DOMAIN-$LASTWEEK.tar.gz" ]; then
      rm -r "$DESTDIR/$DOMAIN-$LASTWEEK.tar.gz2"
      echo -n " Removed last week's backup."
    fi
   echo ""
  fi
done
echo ""
if [ $FAILED == `true` ]; then
  exit 1
fi


So, yeah... That's it! If you need something simple that cleans up after itself - you can either install GNU's date for your shell needs, or do as I did, and abuse Perl. ;)