#!/bin/bash
#
# backup.sh - Danny Sauer, 3/2003
# this needs run as root in order to preserve permissions and make device nodes
# also, each host needs root's private key in its .ssh/authorized_hosts
#
# space-separated list of hosts to be backed up
HOSTS="dialin www router dev web2"
# programs with full paths
RSYNC="/usr/bin/rsync"
ARCHIVE_PL="/Users/dsauer/perl/archive.pl"
DATE="/bin/date"
# variables
TODAY=`$DATE +'%Y.%m.%d'`;
BACKUPDIR="/Volumes/servers"
ARCHIVEDIR="$BACKUPDIR/archive"
# verify that our output directories exist before using them
if [ ! -d $ARCHIVEDIR ]; then
mkdir -p $ARCHIVEDIR
fi
if [ ! -d $BACKUPDIR ]; then
mkdir -p $BACKUPDIR
fi
# backup each host
for HOST in $HOSTS; do
echo "backing up $HOST:"
OUT="$ARCHIVEDIR/$TODAY/$HOST"
# archive.pl wants the top output dir to exist and be empty
if [ -d $OUT ]; then
if rmdir $OUT && mkdir -p $OUT; then
echo -e "\twarn: recreated $OUT"
else
echo -e "\t$OUT exists already and is not empty - there will be problems"
echo -e "\ttry 'rm -r $OUT' and run again"
#rm -r $OUT
fi
else
mkdir -p $OUT
fi
# make snapshot directory
echo -e "\tarchiving\t("`$DATE +'%T'`")"
$ARCHIVE_PL $BACKUPDIR/$HOST $OUT
# synchronize backup directory with server
echo -e "\tsyncing\t("`$DATE +'%T'`")"
$RSYNC -z -qa -e ssh --delete --exclude '/proc/*' root@$HOST:/ $BACKUPDIR/$HOST
# print time of completion
echo -e "\tdone\t("`$DATE +'%T'`")"
done
|
#!/usr/bin/perl -w
#
# archive.pl - Danny Sauer, 4/2003
# given a source and destination directory, makes a hardlinked copy of
# the sorce in the destination, recreating symlinks, nodes, and dirs
#
use strict;
my $cp_command = '/sw/bin/cp';
sub archive($$);
sub cp($$);
my $source = shift or die "usage: $0 source_dir destination_dir";
my $dest = shift or die "usage: $0 source_dir destination_dir";
unless( -d $source ){
die "source must be a directory";
}
mkdir($dest);
archive($source, $dest);
1;
# copy one file
# note - symlinks have no permissions, hardlinks have the same permissions
# as the source file, and "cp -a" preserves permissions. Don't use
# "cp -p", though - must use at least "cp -pR" to copy device nodes
sub cp($$){
my $s = shift;
my $d = shift;
if( -l $s ){
# recreate symlink
symlink(readlink($s), $d);
}elsif( -p _ || -S _ || -b _ || -c _ ){
# use system copy call (rewrite this in perl someday)
system("$cp_command -a $s $d");
}else{
# create hardlink
link($s, $d);
}
}
#walk directory tree
# this just wouldn't work with a while(readdir()), so now readdir into @fs
sub archive($$){
my $s = shift;
my $d = shift;
opendir(S, $s) or die "can't opendir '$s': $!";
my @fs = readdir S;
closedir S;
foreach my $f (@fs){
next if($f eq '.' || $f eq '..');
if(-d "$s/$f"){
mkdir("$d/$f");
my $mode = (stat("$s/$f"))[2] & 07777;
my $user = (stat(_))[4];
my $group = (stat(_))[5];
chmod($mode, "$d/$f");
chown($user, $group, "$d/$f");
archive("$s/$f", "$d/$f");
}else{
cp("$s/$f", "$d/$f");
}
}
}
|