D
dan baker
I recently hacked together a little utility to backup files from
multiple remote hosts to a local PC. The host I use for a lot of
websites does not offer nightly backups, and while they haven't
crashed yet, I wanted to pull copies of databases and other files that
get modified by server-side scripts.
I thought that I'd just post the source in case:
- people want to make constructive comments about how to improve the
code
- somebody needs a similar utility and can start with this source and
run with it.
- because I have used a lot of other people's modules, and thought
maybe this
would help somebody else out.
There are two files. The script, and a config file with the host and
file information.
----------------
#! /usr/bin/perl -w
=head1
# ------------------------------------------------------------------------------
Purpose -
This script backs up specific files from the web to local PC. Its
intended to be run nightly by Task Manager on a PC as an "automated"
utility that is capable of getting multiple files from multiple
servers
sequentially. Intended to get databases, or other files that may
have been changed by server-side tools, and archive to a local PC
just for
backup in cases where the Host does not offer nightly backups, or you
may not trust them to DO them.
Input - 'requires' a config file "config_files.txt" that lists
host,user,password
and files to be backed up
Output -
- pulls files from remote webserver and creates a 'mirror' directory
structure below this script on the local computer.
- creates a log file and emails to desigated address for feedback
History -
written by dan_at_dtbakerprojects.com 10/2004
# ------------------------------------------------------------------------------
=cut
# 3456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-
# ------------------------------------------------------------------------------
# ##############################################################################
# hardcoded parameters
$pCGI_debuglog = './debug.txt';
my $cSMTPserver = 'smtp.yourhost.net' ;
my $Sender = '"Your Name"<[email protected]>';
my $Recipient = $Sender ;
my $Subject = 'web backup utility results' ;
my $Type = 'text/plain';
my $Body ='';
# ##############################################################################
# ------------------------------------------------------------------------------
# external modules
use Net::FTP;
use MIME::Lite ;
# ------------------------------------------------------------------------------
# init local vars
my $tempString = '' ;
my @tempList = () ;
my %tempHash = () ;
my $tempStatus = '';
local $host = '';
local $username = '';
local $password = '';
local @FileList = ();
local $LastRun = 0;
my $ftp = '';
my $DirPath = '';
my $LocalPath = '';
my $FileExt = '';
my $CurrType = 'binary';
my $LastType = 'ascii';
# ########################### Start Main Executable code
#######################
# grab the timestamp from debug file to tell when last run
if (-f $pCGI_debuglog ) {
@tempList = stat($pCGI_debuglog);
$LastRun = $tempList[9];
} else {
$LastRun = 0;
}
$cDEBUG = 1 ; # set to 0 NOT to print debug statements to STDERR
# set to 1 for high-level diagnostics
# set to 'verbose' for detailed diagnostics
$cDEBUG_type = 'overwrite' ;
# 'append' | 'overwrite' debug file
# clear and init logfile
if ( $cDEBUG ) {
if ( $cDEBUG_type eq 'append' ) { # append
open( DEBUG_LOG , ">>$pCGI_debuglog" ) or
die "Failed to open log at $pCGI_debuglog because $!" ;
print DEBUG_LOG "appending to log" ;
} else {
open( DEBUG_LOG , ">$pCGI_debuglog" ) or
die "Failed to open log at $pCGI_debuglog because $!" ;
print DEBUG_LOG "cleared log" ;
}
print DEBUG_LOG " at [".scalar(localtime)."]\n" ;
close DEBUG_LOG ;
}
# redirect stderr to the log
# -----
close STDERR ;
open( STDERR , ">>$pCGI_debuglog" ) or
die "Failed to redirect SDTERR because $!" ;
print STDERR "running: $0\n\n" ;
print scalar(localtime)." running: $0\n\n" ;
# ...and leave open for runtime errors
# note that runtime msgs can be printed to STDERR regardless of
$cDEBUG
# ------------------------------------------------------------------------------
require "config_files.txt" ; # pull in the hosts/files to be backed up
# ------------------------------------------------------------------------------
print "\n\n".scalar(localtime)." ...all done, normal exit.\n";
print STDERR "\n\n".scalar(localtime)." ...all done, normal exit.\n";
close STDERR;
# ##############################################################################
# mail the log to admin
open( DEBUG_LOG , "<$pCGI_debuglog" ) ;
$Body = join('',(<DEBUG_LOG>) ) ;
MIME::Lite->send('smtp', $cSMTPserver , Hello=> $cSMTPserver,
Timeout=>60 );
unless ($Type ) { $Type = 'text/plain' }
# send mail
# -----
my $msg = MIME::Lite->new(
From => $Sender ,
To => $Recipient ,
Subject => $Subject ,
Type => $Type ,
Data => $Body
);
$msg->send() ;
# ##############################################################################
exit;
# ##############################################################################
# ##############################################################################
sub GetFiles {
$ftp = Net::FTP->new($host);
print STDERR "\nLogging into $host \n" ;
print "\nLogging into $host \n";
unless ( $ftp->login( $username , $password ) ) {
print "login to $host failed \n";
print STDERR "login to $host failed \n";
sleep 5;
return(1);
}
foreach $File (@FileList) {
# check directory tree
# -----
$LocalPath = '.';
$DirPath = $host.$File ;
$DirPath =~ s/(.+)\/.*$/$1/ ;
unless ( -d $DirPath ) {
print "gotta create local directories first...\n";
@tempList = split ('/', $DirPath );
foreach $tempString ( @tempList ) {
$LocalPath .= "\/$tempString" ;
unless (-d $LocalPath ) {
print "mkdir $LocalPath \n";
mkdir($LocalPath , 0777);
}
}
}
# check type
# -----
if ( $File =~ m/.*\.(.+)$/ ) {
if ( ( $1 eq 'pdf' ) or
( $1 eq 'jpg' ) or
( $1 eq 'gif' ) )
{
$CurrType = 'binary';
} else {
$CurrType = 'ascii';
}
} else { # no file extension, assume it is binary
$CurrType = 'binary';
}
unless ( $LastType eq $CurrType) {
print "setting type to $CurrType\n";
$ftp->type($CurrType);
$LastType = $CurrType ;
}
# check mod time
# ignoring any time diff between local PC and remote server since
# we will catch a backup the next day even if the times are off a
couple hours
# --------------
if ( ( -f "${host}${File}" ) and
( $ftp->mdtm($File) <= $LastRun )) {
print "$File has not been modified since $LastRun \n";
print STDERR "$File has not been modified since $LastRun \n"
if ($cDEBUG eq 'verbose');
next;
}
# get file
# -----
print "getting $File \n";
print STDERR "getting $File \n" if ($cDEBUG eq 'verbose') ;
$tempStatus = $ftp->get( $File, "${host}${File}" );
unless ( $tempStatus ) {
print "transfer failed, check error log... \n";
print STDERR "getting $File failed\n" ;
}
}
$ftp->quit;
1;
}
# ##############################################################################
1; # ------------------------- end of file
-------------------------------------
.....and the config file example
# config_files.txt
# ----------------
# create a section for each host, and list the files to backup
# be sure to make a call to &GetFiles between each!
# ##############################################################################
$host = 'host1.com' ;
$username = 'user1' ;
$password = 'password1';
@FileList = qw(
/public_html/employees/cgi-bin/databases/DB_OrderInfo
);
&GetFiles;
# ##############################################################################
# ... copy section for another host here...
# ##############################################################################
1; # end of config_files.txt
multiple remote hosts to a local PC. The host I use for a lot of
websites does not offer nightly backups, and while they haven't
crashed yet, I wanted to pull copies of databases and other files that
get modified by server-side scripts.
I thought that I'd just post the source in case:
- people want to make constructive comments about how to improve the
code
- somebody needs a similar utility and can start with this source and
run with it.
- because I have used a lot of other people's modules, and thought
maybe this
would help somebody else out.
There are two files. The script, and a config file with the host and
file information.
----------------
#! /usr/bin/perl -w
=head1
# ------------------------------------------------------------------------------
Purpose -
This script backs up specific files from the web to local PC. Its
intended to be run nightly by Task Manager on a PC as an "automated"
utility that is capable of getting multiple files from multiple
servers
sequentially. Intended to get databases, or other files that may
have been changed by server-side tools, and archive to a local PC
just for
backup in cases where the Host does not offer nightly backups, or you
may not trust them to DO them.
Input - 'requires' a config file "config_files.txt" that lists
host,user,password
and files to be backed up
Output -
- pulls files from remote webserver and creates a 'mirror' directory
structure below this script on the local computer.
- creates a log file and emails to desigated address for feedback
History -
written by dan_at_dtbakerprojects.com 10/2004
# ------------------------------------------------------------------------------
=cut
# 3456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-
# ------------------------------------------------------------------------------
# ##############################################################################
# hardcoded parameters
$pCGI_debuglog = './debug.txt';
my $cSMTPserver = 'smtp.yourhost.net' ;
my $Sender = '"Your Name"<[email protected]>';
my $Recipient = $Sender ;
my $Subject = 'web backup utility results' ;
my $Type = 'text/plain';
my $Body ='';
# ##############################################################################
# ------------------------------------------------------------------------------
# external modules
use Net::FTP;
use MIME::Lite ;
# ------------------------------------------------------------------------------
# init local vars
my $tempString = '' ;
my @tempList = () ;
my %tempHash = () ;
my $tempStatus = '';
local $host = '';
local $username = '';
local $password = '';
local @FileList = ();
local $LastRun = 0;
my $ftp = '';
my $DirPath = '';
my $LocalPath = '';
my $FileExt = '';
my $CurrType = 'binary';
my $LastType = 'ascii';
# ########################### Start Main Executable code
#######################
# grab the timestamp from debug file to tell when last run
if (-f $pCGI_debuglog ) {
@tempList = stat($pCGI_debuglog);
$LastRun = $tempList[9];
} else {
$LastRun = 0;
}
$cDEBUG = 1 ; # set to 0 NOT to print debug statements to STDERR
# set to 1 for high-level diagnostics
# set to 'verbose' for detailed diagnostics
$cDEBUG_type = 'overwrite' ;
# 'append' | 'overwrite' debug file
# clear and init logfile
if ( $cDEBUG ) {
if ( $cDEBUG_type eq 'append' ) { # append
open( DEBUG_LOG , ">>$pCGI_debuglog" ) or
die "Failed to open log at $pCGI_debuglog because $!" ;
print DEBUG_LOG "appending to log" ;
} else {
open( DEBUG_LOG , ">$pCGI_debuglog" ) or
die "Failed to open log at $pCGI_debuglog because $!" ;
print DEBUG_LOG "cleared log" ;
}
print DEBUG_LOG " at [".scalar(localtime)."]\n" ;
close DEBUG_LOG ;
}
# redirect stderr to the log
# -----
close STDERR ;
open( STDERR , ">>$pCGI_debuglog" ) or
die "Failed to redirect SDTERR because $!" ;
print STDERR "running: $0\n\n" ;
print scalar(localtime)." running: $0\n\n" ;
# ...and leave open for runtime errors
# note that runtime msgs can be printed to STDERR regardless of
$cDEBUG
# ------------------------------------------------------------------------------
require "config_files.txt" ; # pull in the hosts/files to be backed up
# ------------------------------------------------------------------------------
print "\n\n".scalar(localtime)." ...all done, normal exit.\n";
print STDERR "\n\n".scalar(localtime)." ...all done, normal exit.\n";
close STDERR;
# ##############################################################################
# mail the log to admin
open( DEBUG_LOG , "<$pCGI_debuglog" ) ;
$Body = join('',(<DEBUG_LOG>) ) ;
MIME::Lite->send('smtp', $cSMTPserver , Hello=> $cSMTPserver,
Timeout=>60 );
unless ($Type ) { $Type = 'text/plain' }
# send mail
# -----
my $msg = MIME::Lite->new(
From => $Sender ,
To => $Recipient ,
Subject => $Subject ,
Type => $Type ,
Data => $Body
);
$msg->send() ;
# ##############################################################################
exit;
# ##############################################################################
# ##############################################################################
sub GetFiles {
$ftp = Net::FTP->new($host);
print STDERR "\nLogging into $host \n" ;
print "\nLogging into $host \n";
unless ( $ftp->login( $username , $password ) ) {
print "login to $host failed \n";
print STDERR "login to $host failed \n";
sleep 5;
return(1);
}
foreach $File (@FileList) {
# check directory tree
# -----
$LocalPath = '.';
$DirPath = $host.$File ;
$DirPath =~ s/(.+)\/.*$/$1/ ;
unless ( -d $DirPath ) {
print "gotta create local directories first...\n";
@tempList = split ('/', $DirPath );
foreach $tempString ( @tempList ) {
$LocalPath .= "\/$tempString" ;
unless (-d $LocalPath ) {
print "mkdir $LocalPath \n";
mkdir($LocalPath , 0777);
}
}
}
# check type
# -----
if ( $File =~ m/.*\.(.+)$/ ) {
if ( ( $1 eq 'pdf' ) or
( $1 eq 'jpg' ) or
( $1 eq 'gif' ) )
{
$CurrType = 'binary';
} else {
$CurrType = 'ascii';
}
} else { # no file extension, assume it is binary
$CurrType = 'binary';
}
unless ( $LastType eq $CurrType) {
print "setting type to $CurrType\n";
$ftp->type($CurrType);
$LastType = $CurrType ;
}
# check mod time
# ignoring any time diff between local PC and remote server since
# we will catch a backup the next day even if the times are off a
couple hours
# --------------
if ( ( -f "${host}${File}" ) and
( $ftp->mdtm($File) <= $LastRun )) {
print "$File has not been modified since $LastRun \n";
print STDERR "$File has not been modified since $LastRun \n"
if ($cDEBUG eq 'verbose');
next;
}
# get file
# -----
print "getting $File \n";
print STDERR "getting $File \n" if ($cDEBUG eq 'verbose') ;
$tempStatus = $ftp->get( $File, "${host}${File}" );
unless ( $tempStatus ) {
print "transfer failed, check error log... \n";
print STDERR "getting $File failed\n" ;
}
}
$ftp->quit;
1;
}
# ##############################################################################
1; # ------------------------- end of file
-------------------------------------
.....and the config file example
# config_files.txt
# ----------------
# create a section for each host, and list the files to backup
# be sure to make a call to &GetFiles between each!
# ##############################################################################
$host = 'host1.com' ;
$username = 'user1' ;
$password = 'password1';
@FileList = qw(
/public_html/employees/cgi-bin/databases/DB_OrderInfo
);
&GetFiles;
# ##############################################################################
# ... copy section for another host here...
# ##############################################################################
1; # end of config_files.txt