Click to See Complete Forum and Search --> : How to backup


edatz
07-27-2010, 06:07 AM
I've never done this before so am completely in the dark.

Situation
There are several directories, full of small files which get changed often on the server.

Objective
To create sipped archives of each directory and email each one to the site owner.

What to do
I have Archive::zip and Compress::Zlib (which I guess are used for this) on my local testbed server (Indigo Perl on PC) and on the live server.

Each back up would be initiated from an admin center by clicking the relevant button for that folder.

I did try a simple script (to see what happened on Indigo Perl) that zips a file in a folder, but the zipfile was empty. That's as far as I've got.

Any ideas or help is appreciated.

Thanks

edatz
07-27-2010, 07:17 AM
I've managed to get the script that failed, to partially work

#### ---- Back up files in .zip
use Archive::Zip;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";

#### ---- variables/settings
$foldertobup = "data";
$zipfilename = "test";

#### ---- Process
$obj = Archive::Zip->new();

# files to store, but I need to each name first.
@files = ("$foldertobup/datone.txt",
"$foldertobup/dattwo.txt");

# create the zipped file
foreach $file (@files) {$obj->addFile($file);}
if ($obj->writeToFileNamed("$zipfilename.zip") != AZ_OK) {
print "Error in archive creation!";
} else {
print "Archive created successfully!";
}
exit;


It does zip up the folder, but I have to name the files inside it first. I tried a grep to no avail (may have done it wrong). Should I read the directory and put all the file names into an array beforehand? Or is there an easier way to do that?

edatz
07-28-2010, 03:20 AM
I've managed to get all files in a directory by changing:
@files = ("$foldertobup/datone.txt",
"$foldertobup/dattwo.txt");
to
@files = <$foldertobup/*>;

That's good. How do I get all the sub directories as well?

I guess everyone is on vacation at the moment :) as I see no replies.

sohguanh
07-28-2010, 03:39 AM
I've managed to get all files in a directory by changing:
@files = ("$foldertobup/datone.txt",
"$foldertobup/dattwo.txt");
to
@files = <$foldertobup/*>;

That's good. How do I get all the sub directories as well?

I guess everyone is on vacation at the moment :) as I see no replies.

You need a recursive function.


sub processDir {
my $inDir = shift @_;

opendir(DIR, $inDir) or die "$!: Error open directory $inDir !";
while (my $file = readdir(DIR)) {
next if $file =~ /^\./;
next if $file =~ /\.zip$/i; #assume you don't want to process zip file
if (-f "$inDir/$file") {
#this is a file
} elsif (-d "$inDir/$file") { #this is a directory
processDir("$inDir/$file"); #recursive call
}
}
closedir(DIR);

}

edatz
07-28-2010, 06:55 AM
sohguanh, I can see that zipping a directory with files and sub-directories is going to be a whole 'nother ball game. The sub dirs was me having a "what if" moment - sorry.

As it stands now I can zip up a directory and it's files.

During this I realized that a date and time on the filename will be needed. This is how the script looks now.


use Archive::Zip;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";

#### ---- day and time
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$fstim = sprintf "%4d%02d%02d%02d%02d\n", 1900+$year,$mon+1,$mday,$hour,$min;

#### ---- variables/settings
## various folder names for test
$afldr = "data";
$bfldr = "dbs";

#### ---- Key for later when libbed
$foldertobup = "$bfldr"; # change variable to input later

@files = <$foldertobup/*>; # works, files only in 1 dir.

#### below gets: Error in archive creation!
$zfn = "$foldertobup$fstim"; ## want date/time in filename
print "$zfn<br>"; ## prints okay here - so it is being seen

&createArchive; # call the sub
sub createArchive {
$obj = Archive::Zip->new();
foreach $file (@files) {$obj->addFile($file);}
if ($obj->writeToFileNamed("$zfn.zip") != AZ_OK) {
print "Error in archive creation!";
} else {
print "Archive created successfully!";
}
exit;
}


As yo can see the "$zfn" works fine during the running of the script and prints to screen (so it is there). However adding that to the zipping process causes an error.

I've tried putting it in at various points but still get the error. Am I missing something?

sohguanh
07-28-2010, 08:12 PM
I have never use the Archive::Zip module before but one simple way to troubleshoot is to instead of $zfn, you first hard-code a fixed filename to see if it works or not.

if ($obj->writeToFileNamed("$zfn.zip") != AZ_OK) {

Change above line to below and see if it still fail or succeed

if ($obj->writeToFileNamed("testing.zip") != AZ_OK) {

edatz
07-29-2010, 03:19 AM
Hi, this gets worse.

I've had to hold fire on the date-time thing because this module does not like paths. If a directory with files is in the same directory as the script, everything will work as I've done it.

But - if the directory to back up is somewhere else and I use a path (say /one/two/three/four/five etc., the thing falls apart.

I took a look at the documentation on CPAN and it's as clear as mud.

The script is one I found. So I'll keep looking to see if there are any others that might be a starting point for me.

It looks like this is going to take ages to sort out, so I'll stop the thread here. Maybe there's another way to zip up files than having to depend on just one module.

Thanks for your time.

edatz
07-29-2010, 07:50 AM
Figured out the paths problem. It works if I have more variables.

use Archive::Zip;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print "Content-type: text/html\n\n";

#### ---- Paths & Variables
$root = "$ENV{'DOCUMENT_ROOT'}";
$rootfldr = "$root/aaaa/bbbb/cccc"; # path to root folder
$ftz = "data"; # name of folder to back up
$zipname = "data";
@files = <$rootfldr/$ftz/*>; # gets all files okay

$obj = Archive::Zip->new();
foreach $file (@files) {$obj->addFile($file);}
if ($obj->writeToFileNamed("archive/$zipname.zip") != AZ_OK) {
print qq ~<div align="center">Error cannot create backup!</div>~;
} else {
print qq ~<div align="center">The Folder <b>($zipname)</b> has been archived.</div>~;
}
exit;

The date thing can wait.

edatz
08-14-2010, 04:03 PM
Got the date resolved, but have had no end of trouble with the zipped file. Unzipped, it contained empty folders for each step in the path to the folder I backed up.

Evidently, "Archive Zip" cannot filter these out. To do that you need: "File Find" and "File Spec Functions qw" modules as well. A small bit of code found by searching differently yielded it and I've got it so that I have exactly what I want in the zipped file :D

Whew! That was a bit of an expedition that was.