Category: Utility
Author/Contact Info zzspectrez
zzspectrez@yahoo.com
Description:

This a script I am working on for doing backups on my home server.
Everything seems to work, but is still a work in progress.
The next step is to have the script read in the archive info from a file so you can have the script do different backup sets.
Eventually, I plan to use the Archive::Tar and File::Temp module so I can remove all the system calls and try to make it more portable so I can use it on my windows machines too.

#!/usr/bin/perl -Tw
######################################################################
+##########
# zzbackupz.pl      =     General Backup utility
######################################################################
+##########
# ver .001        =     11/14/2000 
#                    Initial release hardcoaded to backup /var/spool/m
+ail
# ver .002        =    11/15/2000
#                    Made more configurable for general backups.
#                    Selectable silent or verbose output
#                    Selectable mail output mode        
######################################################################
+##########
#    This program is designed to make a set of backup archives of a us
+er defined
#  list. These backups are then tarred together into a single archive 
+and 
#  compressed with gzip.
#
#    The script can be set in either a verbose or silent mode. There i
+s also an
#  option to email all messages using sendmail. These options allow yo
+u to make
#  backups from the commandline or using cron. 
#
use strict;

######################################################################
+##########
# Variables
######################################################################
+##########

my    $bkup_drive        =    "/dev/hdc4";
my    $mnt_base            =    "/mnt";
my      $tmp_base            =    "/tmp";
my   $bkup_vol_chk        =    "bkup_media_chk";
my    $unmount_drv        =    0;  # 1 = yes 0 = no

# Get Todays date in the form mon-day-year:  ex: jan-02-2000
my    $todays_date        =    join '-', ((    'jan','feb','mar','apr'
+,'may',
                                    'jun','jul','aug','sep','oct',
                                           'nov','dec')[(localtime)[4]
+]),
                                 ((localtime)[3]),
                                 ((localtime)[5]+1900);

my    $archive_name        =    "backup-$todays_date";

my    $tmp_dir            =    "$tmp_base/$archive_name";

my    @msgs            =    ();

## Special Options
my    $msg_status        =    1;        # 1 = STDOUT 0 = SILENT
my    $mail_output        =     0;        # 1 = mail output using Send
+mail 0 = dont mail

## Mail Settings
my    $email_to_addr        =    "your_email\@address.com";
my   $email_to_name        =    "your name";
my    $email_from_addr    =    "srvr_email\@address.com";
my    $email_from_name    =    "zzbackupzz Backup Script";

## Backup Data                [ base_directory, archive_name, @files_t
+o_archive ]
my     @bkups              =     (
                            [ "/home/zzspectrez", "zzspectrez-files.ta
+r", "mail", "bin", "scripts","mp3s"],
                            [ "/var/spool", "mail-spool.tar", "mail/zz
+spectrez", "mail/ghost", "mail/creep",
                                              "mail/spanky" ]         
+                                
                          );

my     @done            =    ();    # archive that were sucessfully ba
+cked up

my     $abn_exit            =    undef;
                                 
$ENV{PATH} = "/bin:/usr/bin";

######################################################################
+##########
# Subroutines
######################################################################
+##########    
sub msg_handler (){
    my $msg    = shift;
    push    @msgs, $msg;            # store message
    print $msg if ($msg_status);    # if not in silent mode print msg 
+to stdout
}    


sub last_msg (){ 
    return $msgs[$#msgs];        #returns last message on the message 
+stack
}

sub erase_dir (){
#safely erase the passed dir
# returns undef if sucessful
#           else err_msg returned
    my $chk_name = shift;
    my $err_msg = undef;
    
    if (-e $chk_name) {
        if (-d $chk_name){ 
            if (-l $chk_name){
                $err_msg = "The directory [$chk_name] is a symbolic li
+nk to another directory.\n";                             
            }else {
                system ('rm','-rf',$chk_name) == 0 or
                    $err_msg = "The directory [$chk_name] was unable t
+o be removed: $!\n";    
            }
        }elsif (-p $chk_name) {
            if (-l $chk_name){
                $err_msg = "[$chk_name] is a symbolic or hard link to 
+a plain file.\n";    
            }else {
                $err_msg = "[$chk_name] is a plain file.\n";    
            }
        }else{
            $err_msg = "[$chk_name] is not a directory and is an unkno
+wn filetype.\n";
        }        
    }else{
        $err_msg = "The directory [$chk_name] does not exist.\n";
    }            
    return $err_msg;
}

sub mail_msg {
    my $subj = shift;
        
    open (ML, "|/usr/lib/sendmail -oi -t") or
        die "Can't run sendmail!: $!\n";
    print ML "From: $email_from_name <$email_from_addr>\n";
    print ML "To: $email_to_name <$email_to_addr>\n";
    print ML "Subject: $subj\n\n";
    print ML @msgs;
    close (ML) or warn "Sendmail did not close properly.\n";    
}    

######################################################################
+##########
# Init and Cleanup Code
######################################################################
+##########
sub startup_init (){
    #Create Temporary directory
    if (-e $tmp_dir){
        if (my $err = &erase_dir($tmp_dir)){
            &msg_handler ("Unable to properly remove directory: $err \
+n");
            $abn_exit = &last_msg;
            &shutdown_cleanup;
            die "zzbackupz aborted.\n";    
        }else{
            unless (mkdir($tmp_dir, 0755)){
                &msg_handler("Unable to created directory [$tmp_dir]: 
+$!\n");
                $abn_exit = &last_msg;
                &shutdown_cleanup;
                die "zzbackupz aborted.\n";
            }
        }
    }else{
        unless (mkdir($tmp_dir, 0775)){
            &msg_handler ("Unable to create directory [$tmp_dir]: $!\n
+");
            $abn_exit = &last_msg;
            &shutdown_cleanup;
            die "zzbackupz aborted.\n";
        }
    }        
    
    #Check if backup drive mounted else mount it
    if (-e "$mnt_base/$bkup_vol_chk") {
        &msg_handler ("Backup media appears to allready be mounted.\n"
+);
        $unmount_drv = 0;          # set status so we do not unmount o
+n exit
    }else{
    #Attempt to mount backup media
        if (system ('mount','-t','vfat',$bkup_drive,$mnt_base) == 0){
            &msg_handler ("Backup media [$bkup_drive] was sucessfully 
+mounted to [$mnt_base].\n");
            $unmount_drv = 1;    # unmount drive on exit
        }else{
            &msg_handler ("Unable to mount backup media: $!\n");
            $abn_exit = &last_msg;
            &shutdown_cleanup;
            die "zzbackupz aborted.\n";
        }
    }    
        
}

sub shutdown_cleanup (){
    if ($abn_exit) {
    #End called due to abnormal exit
        &msg_handler ("Exiting backup due to abnormal exit: $abn_exit"
+);
    }else {
        &msg_handler ("Backup finished.\n");
    }

    &msg_handler ("Removing temporary directory: [$tmp_dir].\n");
    if (-e $tmp_dir){
        if (my $err = &erase_dir($tmp_dir)){
            &msg_handler ("Unable to properly remove directory: $err \
+n");
        }else {
            &msg_handler ("[$tmp_dir] was removed.\n");    
        }    
    }
    
    if ($unmount_drv) {    
        &msg_handler ("Unmounting backup drive.\n");
        if (system('umount',$mnt_base) == 0) {
            &msg_handler ("Sucessfully unmounted [$mnt_base].\n");
        }else{
            &msg_handler ("Unable to unmount [$mnt_base]: $!\n");
        }
    }else{
        &msg_handler ("Not attempting to unmount [$mnt_base]: Was moun
+ted prior to backup or unable to mount.\n");
    }
    
    &mail_msg("zzbackupz backup log for $todays_date") if $mail_output
+;                
}


###########################################################
# Main Program
###########################################################

&startup_init;

foreach my $item ( @bkups ) {
    my ($base, $name, @files) = @$item;        
    unless (chdir $base) {
        &msg_handler ("Skipped backup of [$name], could not change to 
+directory [$base]: $!.\n");
        next;
    }    
    if (system("tar","-cf","$tmp_dir/$name",@files)) {
        &msg_handler ("The tar of [$name] did not complete sucessfully
+.\n");
        next;
    }else {
        &msg_handler ("[$name] was sucesfully tarred.\n");
        push @done, $name;    
    }
}

if (@done) {
    unless (chdir $tmp_dir){
        &msg_handler ("Unable to change to temp directory [$tmp_dir]:$
+!\n");
        $abn_exit = &last_msg;
        &shutdown_cleanup;
        die "zzbackupz aborted.\n";
    }
        
    if (system("tar","-cf",$archive_name,@done)){
        &msg_handler ("The tar of [$archive_name] did not complete suc
+essfully.\n");
        $abn_exit = &last_msg;
        &shutdown_cleanup;
        die "zzbackupz aborted.\n";
    }
    
    if (system("gzip","-f9",$archive_name)){
        &msg_handler ("The gzip of [$archive_name] did not complete su
+cessfully.\n");
        $abn_exit = &last_msg;    
        &shutdown_cleanup;
        die "zzbackupz aborted.\n";
    }
        if (system("mv","$archive_name.gz",$mnt_base)){
        &msg_handler ("Backup file was not sucessfully moved to zip dr
+ive.\n");        
        $abn_exit = &last_msg;
        &shutdown_cleanup;
        die "zzbackupz aborted.\n";
    }    
}else {
    &msg_handler ("No files backed up.\n");
}    

&shutdown_cleanup;