#!/usr/bin/perl # Last change: PFB 7 May 2001 4:16 am # selected_backup.cgi ################################################################################### # POD Documentation =head1 PROGRAM NAME AND AUTHOR Selected Backup v1.2 by Peter F. Brown peterbrown@worldcommunity.com Build Date: March 22, 2001 =PURPOSE Backs up selected data with options to email the file, and options to clean up old backup files =COPYRIGHT Copyright 2001 Peter F. Brown (The World Community Network) Selected Backup complies with the GNU GENERAL PUBLIC LICENSE and is released as "Open Source Software". NO WARRANTY IS OFFERED FOR THE USE OF THIS SOFTWARE =BUG REPORTS AND SUPPORT Send bug reports to peterbrown@worldcommunity.com. Visit the author's web site at 'worldcommunity.com' to view information about support, customer quotes, a resume link, and fees for custom Perl/MySQL programming. =OBTAINING THE LATEST VERSION ==> Get the most recent version of this program at: http://worldcommunity.com/opensource =cut ################################################################################### use POSIX qw(strftime); use Time::Local; use Cwd; # VARIABLE SET UP SECTION # .................................. use MIME::Lite; # if you don't have the MIME::Lite library # (it's at CPAN), then comment out the # line 'use MIME::Lite', and set the variable, # $email_backup (below) to 'no'. # You'll also have to comment out the section # below marked as 'MIME::Lite BLOCK' # MIME::Lite is used to email the tar.gzip file # as an attachment. If you're not doing this, # then you don't need the library. $mailprog = "/var/qmail/bin/qmail-inject -h"; # $mailprog = '/usr/lib/sendmail -t -oi'; # $mailprog = '/usr/sbin/sendmail -t -oi'; # sendmail is more common $admin_email_to = "admin\@yourdomain.com"; $admin_email_from = "webmaster\@yourdomain.com"; # the email for error messages, etc. # !!! PLEASE CHANGE THIS EMAIL ADDRESS # WHEN YOU INSTALL IT ON YOUR SERVER !!! $site_name = 'My Domain'; $subject = "/ (root) Backup Done for $site_name"; # subject is the email subject $backup_dir = '/mnt/backup'; # the backup dir should normally be # OUTSIDE of your web document root # this directory must be writable by the script. $file_prefix = 'bak.root'; # the file prefix is also used to match files # for the deletion of old files. It's a real # 'PREFIX', it will be placed at the front of # each file name $include_files = '/usr/local/sbin/root.root.inc.txt'; $exclude_files = '/usr/local/sbin/root.root.exc.txt'; $tar_options = '-p'; # hardcoded options include 'c, T, X, f' # v = verbose, p = retain permissions # W = verify # NOTE: we don't use -v for a / root backup, # because of the large number of output lines $nice_cmd = '/bin/nice'; $tar_cmd = '/bin/tar'; $gzip_cmd = '/bin/gzip'; $date_text = strftime("%Y-%m-%d_%H.%M.%S", localtime); # the date_text var becomes part of the backup file name # see notes about 'backup_date_string' at end of file $increments_to_save = 3; $seconds_multiplier = 86400; $increment_type = "Day(s)"; $seconds_to_save = $increments_to_save * $seconds_multiplier; # increment_type is used for the text output, # and has no impact on the math. # one could set increment type to "Minute(s)" # or "Hour(s)" or "Day(s)" or "Week(s)", etc. # Just set the seconds_to_save number to # the correct number of seconds, i.e: # minute: 60 / hour: 3600 / day: 86400 # week: 604800 # these variables control how many increments # (e.g. 'days') worth of # backup files to save. Files with # timestamps older than this will be deleted each time # the script is run. Note that the file modification # time is used - NOT the file name. # This may have to be modified on non-Linux boxes. $email_backup = 'no'; # set email_backup to 'yes' if you want to email the # tar.gzip file to the email_admin # note that it might be large! # However, the backup is useless if your machine # crashes before you copy the data OFF of your machine!!! # Thus, I recommend emailing it. # I go as far as copying my desktop hard drive to a # backup drive, and then storing the backup drive in # a safe deposit box at the bank. # DATA IS REALLY HARD TO REPLACE. # $fpt_backup # this is on the todo list. $chmod_backup_file = 'yes'; # set to 'yes' if you want to use it # (you DO NOT want to set the backup file to 600 # unless you can ftp in as the user that # the script runs as.) # END OF SETUP VARIABLES ################################################################################### # YOU NORMALLY WON'T HAVE TO MODIFY ANYTHING BELOW THIS LINE ################################################################################### MIME::Lite->send('sendmail', "$mailprog"); chdir ("$backup_dir"); print qq~Processing Backups in $backup_dir\n~; $body_text = "Processing Backups in $backup_dir\n\n"; # tar and compress #............................................................................ print qq~\nTarring and Gzipping Files:\n~; $body_text .= "\nTarring and Gzipping Files:\n"; $backup_tar_file = $backup_dir . "/" . $file_prefix . "." . $date_text . "_.tar"; $body_text .= `$nice_cmd $tar_cmd $tar_options -c -T $include_files -X $exclude_files -f $backup_tar_file`; $body_text .= `$nice_cmd $gzip_cmd $backup_tar_file`; $backup_gzip_file = $backup_tar_file . ".gz"; if ( $chmod_backup_file eq 'yes' ) { chmod 0600, $backup_gzip_file; } $body_text .= "\nCreated Tar.Gzip File: $backup_gzip_file\n"; # now clean out old files #............................................................................ &clean_old_files; # now get list of current backup files, with sizes $body_text .= "\nBackup Files and Sizes\n\n"; $body_text .= `ls -la`; # now email admin notification of backup, with attached file option #............................................................................ $body_text .= "\n\nDone!\n\n"; if ( $email_backup eq 'yes' ) { # MIME::Lite BLOCK # comment this block out if you don't have MIME::Lite installed # Create a new multipart message: $msg = new MIME::Lite From =>"$admin_email_from", To =>"$admin_email_to", Subject =>"$subject", Type =>"multipart/mixed"; # Add parts attach $msg Type =>"TEXT", Data =>"\nTar.Gzip File\n[$backup_gzip_file]\nAttached\n$body_text"; attach $msg Type =>"x-gzip", Encoding =>"base64", Path =>"$mysql_backup_dir/$backup_gzip_file"; Filename =>"$backup_gzip_file"; $msg->send || die print "Error in Mailing Program!"; # comment out the block above if you don't have MIME::Lite installed } else { # just send notice, without attachment &mail_to($admin_email_to, $admin_email_from, $subject, $body_text, $admin_email_from); } print "Done!\n"; exit; ################################################################################### # error_message sub error_message { # &error_message($error_text); my ($error_text) = @_; my $subject = "$site_name MySQL Backup Error"; &mail_to($admin_email_to, $admin_email_from, $subject, $error_text, $admin_email_from); print qq~ \n $subject\n $error_text\n ~; exit; } ################################################################################### # mail_to sub mail_to { # &mail_to($email_to, $email_from, $subject, $mail_body, $reply_to); my ($email_to, $email_from, $subject, $mail_body, $reply_to) = @_; if ( $reply_to !~ /\@/ ){$reply_to = $email_from;} open (MAIL, "|$mailprog") || die &error_message(qq~Error!
Can't open $mailprog!~); print MAIL "To: $email_to\n"; print MAIL "From: $email_from\n"; print MAIL "Subject: $subject\n"; print MAIL "Reply-To: $reply_to\n"; print MAIL "\n"; print MAIL "$mail_body"; print MAIL "\n"; close (MAIL); } ################################################################################### # clean_old_files sub clean_old_files { # $backup_dir # $seconds_to_save = $increments_to_save * $seconds_multiplier; $save_time = time() - $seconds_to_save; $old_files = 0; print qq~\nRemoving Files Older than $increments_to_save $increment_type\n~; $body_text .= "\nRemoving Files Older than $increments_to_save $increment_type\n"; $body_text .= "\nFiles to be removed:\n\n"; opendir (DIRHANDLE, $backup_dir); # we use $file_prefix to make it safer; we don't want to delete # any files except those matching the file spec @filelist = grep { /^$file_prefix\./ } readdir(DIRHANDLE); closedir (DIRHANDLE); @sortlist = sort(@filelist); # loop through directory foreach $infile (@sortlist) { $infile = "$backup_dir/$infile"; # check if file is a directory if ( -d $infile ) { print "- Skipping: $infile -\n"; next; } ($modtime) = (stat($infile))[9]; if ( $modtime < $save_time ) { # file is older, so delete it $old_files++; $body_text .= "\n" . `ls -la $infile`; $delete_count = unlink "$infile"; if ( ! -e $infile and $delete_count == 1 ) { $body_text .= "$delete_count File Removed: ($infile\)\n"; } else { $body_text .= "\nProblem Removing File: $infile\n"; } } else { $body_text .= "\n- Keeping: $infile -\n"; } } } ################################################################################### # backup_date_string notes # this is a handy method to initialize date display # it requires the POSIX and Time::Local calls above # I use this because I got tired of messing with date routines # strftime notes: # %A - full weekday name # %B - full month name # %m - month as a decimal number (range 01 to 12). # %d - day with leading zero # %Y - 4 digit year # %H - hour as a decimal number using a 24-hour clock (range 00 to 23). # %l - hour using 12 hour clock, with no leading zero # %M - minute as decimal, 00-59 # %S - second as a decimal number (range 00 to 61). # %p - AM or PM # %Z - time zone letters # e.g: $backup_date_string = strftime("%Y-%m-%e_%H.%M.%S", localtime); ###################################################################################