Subversion Repositories general

Rev

Rev 1151 | Rev 1153 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1149 dev 1
#!/usr/bin/perl
2
# fsbackup - file system backup and synchronization utility. 
3
#
4
# http://www.opennet.ru/dev/fsbackup/
5
# Copyright (c) 2001-2002 by Maxim Chirkov. <mc@tyumen.ru>
6
#
1152 dev 7
# ëÌÀÞÉ:
8
# -n - ÓÏÚÄÁÅÍ ÎÏ×ÙÊ ÁÒÈÉ× ÎÅÚÁ×ÉÓÉÍÏ ÏÔ ÓÏÓÔÏÑÎÉÑ ÈÜÛÁ.
9
# -f - full_backup - ÐÏÌÎÙÊ ÂÜËÁÐ × ÁÒÈÉ×, ÂÅÚ ÈÜÛÁ.
10
# -h - hash - ÔÏÌØËÏ ÇÅÎÅÒÁÃÉÑ ÈÜÛÁ, ÂÅÚ ÐÏÍÅÝÅÎÉÑ ÆÁÊÌÏ× × ÁÒÈÉ×.
11
# -c - clean - ÏÞÉÓËÁ ÈÒÁÎÉÌÉÝÁ Ó ÉÎËÒÅÍÅÎÔÁÌØÎÙÍ ÂÜËÁÐÏÍ É ÓÏÚÄÁÎÉÅ ÎÏ×ÏÇÏ ÂÜËÁÐÁ.
1149 dev 12
 
13
#############################################
1152 dev 14
use constant DB_DEF_CACHE_SIZE => 4096000; # òÁÚÍÅÒ ËÜÛÁ ÄÌÑ ÒÁÚÍÅÖÅÎÉÑ ÈÜÛÁ × ÐÁÍÑÔÉ
1149 dev 15
 
16
use POSIX;
17
use File::Find;
18
use Digest::MD5 qw(md5_base64);
19
use Net::FTP;
20
use DB_File;
21
 
22
use constant VERB_SILENT => 0; # Silent mode, suspend all output.
23
use constant VERB_ERROR => 1; # Output all errors and warnings.
24
use constant VERB_ALL => 2; # Output all the  available  data.
25
 
26
my $list_lines_cnt = 0;
27
my $del_lines_cnt = 0;
28
my $cur_time = time();
29
my %active_hash_last;
30
my %active_hash_new;
31
my $cfg_new_flag = 0;
32
my $cfg_clean_flag = 0;
33
my $config = 0;
1152 dev 34
my $cur_backup_size = 1536; # òÁÚÍÅÒ ÂÌÏËÁ tar
1149 dev 35
my $backup_file_base;
36
my $prog_pgp_filter;
37
my $prog_gzip_filter;
38
my $arc_ext;
39
my $ftp;
40
my $cur_increment_level;
41
my $cur_dir;
42
my $cur_path;
43
my $cur_file;
44
my $cur_pathitem;
45
my $file_fullpath;
46
my $file_fullpath_md5;
47
my $key;
48
my $dbobj_new;
49
my $dbobj_last;
50
my $db_hashinfo;
51
my $db_hashinfo2;
52
my $file;
53
my @volume_position=(0);
1152 dev 54
my @fs_path=();	       #  /dir[/file] - ÐÕÔØ Ë ÆÁÊÌÕ/ÄÉÒÅËÔÏÒÉÉ ÄÌÑ ÂÜËÁÐÁ.
55
my @fs_notpath=();     #  ! - ÏÔÒÉÃÁÎÉÅ ÐÕÔÉ, ÎÅ ÐÏÍÅÝÁÔØ × ÂÜËÁÐ. ÷ÓÅÇÄÁ ÄÏÌÖÅÎ ÂÙÔØ ÐÅÒ×ÙÍ ÓÉÍ×ÏÌÏÍ.
56
my @fs_mask=();        #  =~ - ÍÁÓËÁ ÄÌÑ ÆÁÊÌÁ ÉÌÉ ÄÉÒÅËÔÏÒÉÉ, Á ÎÅ ÁÂÓÏÌÀÔÎÙÊ ÐÕÔØ. ðÅÒ×ÙÊ ÉÌÉ ×ÔÏÒÏÊ ÓÉÍ×ÏÌ.
57
my @fs_filemask=();    #  f~ - ÍÁÓËÁ ÄÌÑ ÆÁÊÌÁ. ðÅÒ×ÙÊ ÉÌÉ ×ÔÏÒÏÊ ÓÉÍ×ÏÌ.
58
my @fs_dirmask=();     #  d~ - ÍÁÓËÁ ÄÌÑ ÄÉÒÅËÔÏÒÉÉ. ðÅÒ×ÙÊ ÉÌÉ ×ÔÏÒÏÊ ÓÉÍ×ÏÌ.
59
my @fs_notmask=();     #  =! - "îå" ÍÁÓËÁ ÄÌÑ ÆÁÊÌÁ ÉÌÉ ÄÉÒÅËÔÏÒÉÉ, Á ÎÅ ÁÂÓÏÌÀÔÎÙÊ ÐÕÔØ. ðÅÒ×ÙÊ ÉÌÉ ×ÔÏÒÏÊ ÓÉÍ×ÏÌ.
60
my @fs_notfilemask=(); #  f! - "îå" ÍÁÓËÁ ÄÌÑ ÆÁÊÌÁ. ðÅÒ×ÙÊ ÉÌÉ ×ÔÏÒÏÊ ÓÉÍ×ÏÌ.
61
my @fs_notdirmask=();  #  d! - "îå" ÍÁÓËÁ ÄÌÑ ÄÉÒÅËÔÏÒÉÉ. ðÅÒ×ÙÊ ÉÌÉ ×ÔÏÒÏÊ ÓÉÍ×ÏÌ.
1149 dev 62
 
1152 dev 63
# ------------- ïÂÒÁÂÏÔËÁ ÐÁÒÁÍÅÔÒÏ× ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ
1149 dev 64
 
65
if ($ARGV[0] eq "-n" || $ARGV[0] eq "-h" || $ARGV[0] eq "-f" || $ARGV[0] eq "-c"){
66
    $cfg_new_flag=1;
67
    $config = $ARGV[1];
68
} else {
69
    $cfg_new_flag=0;
70
    $config = $ARGV[0];
71
}
72
 
73
if ( ! -f $config){
74
    die "Usage: fsbackup.pl [-n|-f|-h|-c] config_name\n";
75
}
76
 
1152 dev 77
 
1149 dev 78
require "$config";
79
 
80
if ( ! -d $cfg_cache_dir){
81
    die "\$cfg_cache_dir ($cfg_cache_dir) not found. Set \$cfg_cache_dir varisble in fsbackup.pl\n";
82
}
83
 
1152 dev 84
$cfg_time_limit *= 60 * 60 * 24; # äÎÉ × ÓÅËÕÎÄÙ.
85
$cfg_size_limit *= 1024;	 # ëÉÌÏÂÁÊÔÙ × ÂÁÊÔÙ.
86
$cfg_maximum_archive_size *= 1024;	 # ëÉÌÏÂÁÊÔÙ × ÂÁÊÔÙ.
1149 dev 87
 
1151 dev 88
chdir($cfg_root_path);
1149 dev 89
 
90
if ($ARGV[0] eq "-h"){
91
    $cfg_backup_style = "hash";
92
}
93
if ($ARGV[0] eq "-f" ){
94
    $cfg_backup_style = "full_backup";
95
}
96
 
97
if ($ARGV[0] eq "-c" ){
98
    $cfg_clean_flag=1;
99
} else {
100
    $cfg_clean_flag=0;
101
}
102
 
1152 dev 103
#------------------- ðÒÏ×ÅÒÑÅÍ ÐÅÒÅÍÅÎÎÙÅ × ÆÁÊÌÅ ËÏÎÆÉÇÕÒÁÃÉÉ.
1149 dev 104
if ($cfg_backup_name !~ /^[\w\d\_]+$/){
105
    die "Found illegal characters in $cfg_backup_name ($cfg_backup_name).";
106
}
107
 
108
if (! grep {$_ eq $cfg_checksum} ("md5", "timesize")){
109
    die "Unknown checksum method:\$cfg_checksum=$cfg_checksum (allowed md5 or timesize)\n";
110
}
111
 
112
if (! grep {$_ eq $cfg_backup_style} ("backup", "full_backup", "sync", "hash")){
113
    die "Unknown backup_style:\$cfg_backup_style=$cfg_backup_style\n";
114
}
115
 
116
 
117
if ($cfg_backup_style eq "full_backup" || $cfg_backup_style eq "hash"){
118
    $cfg_new_flag=1;
119
    $cfg_clean_flag=1;
120
}
121
 
122
if (! grep {$_ eq $cfg_type} ("local", "remote_ssh", "remote_ftp")){
123
    die "Unknown backup target:\$cfg_type=$cfg_type\n";
124
}
125
 
126
if (($cfg_type eq "local") && (! -d $cfg_local_path)){
127
    die "Can't find \$cfg_local_path ($cfg_local_path)";
128
}
129
 
130
if ($cfg_backup_style eq "backup"){
131
    my ($sec,$min,$hour,$mday,$mon,$year) = localtime($cur_time);
132
    $backup_file_base = sprintf ("%s-%4.4d.%2.2d.%2.2d.%2.2d.%2.2d.%2.2d",
133
		$cfg_backup_name,$year+1900,$mon+1,$mday,$hour,$min,$sec);
134
}else{
135
    $backup_file_base="$cfg_backup_name";
136
}
137
 
138
print "Creating $cfg_type $cfg_backup_style: $cfg_backup_name\n" if ($cfg_verbose == &VERB_ALL);
139
 
140
if ($cfg_pgp_userid ne "" && $prog_pgp ne ""){
141
    print "PGP: enabled\n" if ($cfg_verbose == &VERB_ALL);
142
 
143
#    PGP 2.6 (pgp)
144
#    $prog_pgp_filter="| $prog_pgp -ef $cfg_pgp_userid -z'$cfg_pgp_userid' ";
145
#    PGP 5.0 (pgpe)
146
#    $prog_pgp_filter="| $prog_pgp -f $cfg_pgp_userid";
147
#    GnuPG (pgp)
148
    $prog_pgp_filter="| $prog_pgp -v --batch -e -r $cfg_pgp_userid";
149
} else {
150
    $prog_pgp_filter="";
151
}
152
 
153
if ($prog_gzip ne ""){
154
    $prog_gzip_filter="| $prog_gzip";
155
    $arc_ext=".gz";
156
} else {
157
    $prog_gzip_filter="";
158
    $arc_ext="";
159
 
160
}
161
 
162
if (! -d "$cfg_cache_dir/$cfg_backup_name"){
163
    mkdir("$cfg_cache_dir/$cfg_backup_name", 0700);
164
}
165
 
1152 dev 166
# ---------- áËÔÉ×ÉÒÕÅÍ FTP ÓÏÅÄÉÎÅÎÉÅ 
1149 dev 167
 
168
ftp_connect();
169
 
1152 dev 170
#----------- ÷ÙÞÉÓÌÑÅÍ ÕÒÏ×ÅÎØ ÉÎËÒÅÍÅÎÔÁÌØÎÏÓÔÉ.
1149 dev 171
if ($cfg_increment_level != 0 && $cfg_backup_style eq "backup"){
1152 dev 172
    $cur_increment_level=0;
173
 
174
    if ( $cfg_type eq "local"){
175
	opendir( DIR, "$cfg_local_path");
176
	while ($cur_dir = readdir DIR){
177
	    if ($cur_dir =~ /\-0\.tar${arc_ext}$/){
178
	        $cur_increment_level++;
179
	    }
180
	}
181
	closedir (DIR);
182
 
183
    } elsif ( $cfg_type eq "remote_ssh"){
184
 
185
	open (DIR, "$prog_ssh -l $cfg_remote_login $cfg_remote_host 'ls $cfg_remote_path/' |") || print "SSH connection failed: $?\n";
186
	while (<DIR>){
187
	    $cur_dir = $_;
188
	    if ($cur_dir =~ /\-0\.tar${arc_ext}$/){
189
	        $cur_increment_level++;
190
	    }
191
	}
192
	close (DIR);
193
    } elsif ( $cfg_type eq "remote_ftp"){
194
	foreach $cur_dir ($ftp->ls()){
195
	    if ($cur_dir =~ /\-0\.tar${arc_ext}$/){
196
	        $cur_increment_level++;
197
	    }
198
	}
1151 dev 199
    }
200
    if ($cur_increment_level >= $cfg_increment_level){
1149 dev 201
	$cfg_new_flag=1;
202
	$cfg_clean_flag=1;
203
    }
204
    print "Current increment number: $cur_increment_level\n" if ($cfg_verbose == &VERB_ALL);
205
}
206
################################################
1152 dev 207
#----------- óÞÉÔÙ×ÁÅÍ ÈÜÛ × ÐÁÍÑÔØ.
1149 dev 208
 
209
if ( (-f "$cfg_cache_dir/$cfg_backup_name/.hash" || $cfg_type ne "local" ) && $cfg_new_flag == 0){
1152 dev 210
# óÞÉÔÙ×ÁÅÍ ÔÅËÕÝÉÊ ÈÅÛ × ÐÁÍÑÔØ.
1149 dev 211
 
212
if ( $cfg_type eq "local"){
213
    rename ("$cfg_cache_dir/$cfg_backup_name/.hash", "$cfg_cache_dir/$cfg_backup_name/.hash.last");
214
}elsif ( $cfg_type eq "remote_ssh"){
215
    system ("$prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat $cfg_remote_path/.hash' > $cfg_cache_dir/$cfg_backup_name/.hash.last") == 0 || print "SSH connection failed: $?\n";
216
} elsif ( $cfg_type eq "remote_ftp"){
217
    unlink ("$cfg_cache_dir/$cfg_backup_name/.hash.last");
218
    $ftp->get(".hash", "$cfg_cache_dir/$cfg_backup_name/.hash.last")|| print "FTP error, Can't GET .hash\n";
219
}
220
        $db_hashinfo = new DB_File::HASHINFO ;
221
        $db_hashinfo->{'cachesize'} =  DB_DEF_CACHE_SIZE;
222
        if (! ($dbobj_last = tie(%active_hash_last, "DB_File", "$cfg_cache_dir/$cfg_backup_name/.hash.last", O_RDWR|O_CREAT, 0644, $db_hashinfo ))){
223
	    print "WARNING: Error in hash, creating full backup.\n" if ($cfg_verbose >= &VERB_ERROR);
224
	    unlink "$cfg_cache_dir/$cfg_backup_name/.hash.last";
225
	    $dbobj_last = tie(%active_hash_last, "DB_File", "$cfg_cache_dir/$cfg_backup_name/.hash.last", O_RDWR|O_CREAT, 0644, $db_hashinfo )||print "Can't create or open DB File!";
226
	}
227
	# $dbobj->del($key);
228
	# $dbobj->sync();
229
 
230
}
231
 
1152 dev 232
# úÁËÒÙ×ÁÅÍ ftp ÓÏÅÄÉÎÅÎÉÅ. óÌÅÄÕÀÝÉÊ ÂÌÏË ÍÏÖÅÔ ×ÙÐÏÌÎÑÔØÓÑ ÇÏÒÁÚÄÏ ÄÏÌØÛÅ 
233
# ÞÅÍ ÔÁÊÍÁÕÔ ftp.
1149 dev 234
if ( $cfg_type eq "remote_ftp"){
235
    $ftp->quit;
236
}
1152 dev 237
#óÏÚÄÁÅÍ ÎÏ×ÙÊ ÈÅÛ.
1149 dev 238
unlink("$cfg_cache_dir/$cfg_backup_name/.hash");
239
$db_hashinfo2 = new DB_File::HASHINFO ;
240
$db_hashinfo2->{'cachesize'} =  100000;
241
$dbobj_new = tie(%active_hash_new, "DB_File", "$cfg_cache_dir/$cfg_backup_name/.hash", O_RDWR|O_CREAT, 0644, $db_hashinfo2) || print "Can't create or open DB File!\n";
242
 
1152 dev 243
# óÏÚÄÁÅÍ ÓÐÉÓÏË ÆÁÊÌÏ× ÄÌÑ ÐÏÍÅÝÅÎÉÑ × ÁÒÈÉ×.
1149 dev 244
open (LIST, ">$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list")|| print "Can't create list file ($cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list).\n";
245
flock (LIST, 2);
246
 
1152 dev 247
# óÏÚÄÁÅÍ ÓÐÉÓÏË ÄÉÒÅËÔÏÒÉÊ × ÁÒÈÉ×Å.
1149 dev 248
open (DIRS, ">$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.dir")|| print "Can't create list file ($cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.dir).\n";
249
flock (DIRS, 2);
250
 
1152 dev 251
# óÞÉÔÙ×ÁÅÍ ÓÐÉÓÏË ÐÏÄÌÅÖÁÝÉÈ ÂÜËÁÐÕ ÄÉÒÅËÔÏÒÉÊ × ÐÁÍÑÔØ.
1151 dev 252
 
1149 dev 253
while(<DATA>){
254
    chomp;
255
    $cur_path = $_;
256
    if ($cur_path =~ /^\!(.*)$/){		#  !
257
	push @fs_notpath, $1;
258
 
259
    } elsif ($cur_path =~ /^\=\~(.*)$/){	#  =~
260
	push @fs_mask, $1;
261
 
262
    } elsif ($cur_path =~ /^f\~(.*)$/){		#  f~
263
	push @fs_filemask, $1;
264
 
265
    } elsif ($cur_path =~ /^d\~(.*)$/){		#  d~
266
	push @fs_dirmask, $1;
267
 
268
    } elsif ($cur_path =~ /^\=\!(.*)$/){	#  =!
269
	push @fs_notmask, $1;
270
 
271
    } elsif ($cur_path =~ /^f\!(.*)$/){		#  f!
272
	push @fs_notfilemask, $1;
273
 
274
    } elsif ($cur_path =~ /^d\!(.*)$/){		#  d!
275
	push @fs_notdirmask, $1;
276
 
277
    } elsif ($cur_path =~ /^#/ || $cur_path =~ /^\s*$/){ #  comment
278
	next;
279
 
280
    } elsif ($cur_path =~ /[\/\w]+/) {		#  /dir[/file]
1151 dev 281
	push @fs_path, $cur_path;
1149 dev 282
 
283
    } else {
284
	print STDERR "Syntax error: $cur_path, ingnored.\n" if ($cfg_verbose >= &VERB_ALL);
285
    }
286
}
287
 
288
#--------------------------------------------------------------------
1152 dev 289
# ðÏÓÌÅÄÏ×ÁÔÅÌØÎÏ ÐÒÏÓÍÁÔÒÉÒÉ×ÁÅÍ ×ÅÓØ ÓÐÉÓÏË ÄÉÒÅËÔÏÒÉÊ ÏÔÍÅÞÅÎÎÙÈ ÄÌÑ ÂÜËÁÐÁ
1149 dev 290
 
291
 
292
foreach $cur_pathitem (@fs_path){
293
    print "Adding $cur_pathitem....\n" if ($cfg_verbose == &VERB_ALL);
294
    find (\&add_to_backup, $cur_pathitem);
295
    print "done\n" if ($cfg_verbose == &VERB_ALL);
296
}
297
close (LIST);
298
close (DIRS);
299
#------------
1152 dev 300
# óÏÓÔÁ×ÌÑÅÍ ÓÐÉÓÏË ÕÄÁÌÅÎÎÙÈ ÆÁÊÌÏ×.
1149 dev 301
 
302
    open (DEL, ">$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del")|| print "Can't create list file ($cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del).\n";
303
    flock (DEL, 2);
304
    if ($cfg_backup_style ne "hash"){
305
	while(($file, $key)= each(%active_hash_last)){
306
	    $file =~ s/\'/\'\\\'\'/g;
307
	    $file =~ s/^\/(.*)$/$1/;
308
	    print DEL "rm -rf '$file'\n";
309
	    $del_lines_cnt++;
310
	}
311
    }
312
    close(DEL);
313
 
1152 dev 314
# úÁÐÉÓÙ×ÁÅÍ ÈÜÛ ÎÁ ÄÉÓË.
1149 dev 315
$dbobj_new->sync();
316
untie %active_hash_new;
317
untie %active_hash_last;
318
 
1152 dev 319
chdir ("/"); # ðÅÒÅÈÏÄÉÍ × ËÏÒÅÎØ, ÔÁË ËÁË ×ÓÅ ÐÕÔÉ Õ ÎÁÓ ÂÅÚ ËÏÒÎÅ×ÏÇÏ /
1149 dev 320
 
1152 dev 321
# áËÔÉ×ÉÒÕÅÍ FTP ÓÏÅÄÉÎÅÎÉÅ ×ÔÏÒÏÊ ÒÁÚ.
1149 dev 322
ftp_connect();
323
 
324
#------------
1152 dev 325
# åÓÌÉ ÔÏÌØËÏ ÏÂÎÏ×ÌÑÅÍ ÈÜÛ, ÔÏ ÚÁÐÉÓÙ×ÁÅÍ ÅÇÏ É ×ÙÈÏÄÉÍ.
1149 dev 326
 
1152 dev 327
if ($cfg_backup_style eq "hash"){ # ôÏÌØËÏ ÓÏÚÄÁÔØ ÈÜÛØ ÂÅÚ ÁÒÈÉ×ÉÒÏ×ÁÎÉÑ.
1149 dev 328
 
329
    if ( $cfg_type eq "local"){
330
	system( "cp -f $cfg_cache_dir/$cfg_backup_name/.hash $cfg_local_path/.hash") == 0 || print "Local FS copy hash failed: $?";
331
    } elsif ( $cfg_type eq "remote_ssh"){
332
	system( "cat $cfg_cache_dir/$cfg_backup_name/.hash | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/.hash'") == 0 || print "SSH connection failed (copy hash): $?\n";
333
    } elsif ( $cfg_type eq "remote_ftp"){
334
	$ftp->delete(".hash");
335
	$ftp->put("$cfg_cache_dir/$cfg_backup_name/.hash", ".hash")|| print "Can't upload .hash to remote server via FTP\n";
336
    }
337
    exit (0);
338
}
339
 
340
#------------
1152 dev 341
# áÒÈÉ×ÉÒÕÅÍ É ÐÅÒÅÄÁÅÍ × ÈÒÁÎÉÌÉÝÅ.
1149 dev 342
 
1152 dev 343
if ($list_lines_cnt == 0 && $del_lines_cnt == 0){
1149 dev 344
    print "WARNING: Nothing to backup.\n" if ($cfg_verbose >= &VERB_ALL);
345
    exit;
346
}
347
if ( $cfg_type eq "local"){
348
 
349
    print "Storing local backup...\n" if ($cfg_verbose == &VERB_ALL);
350
    if ($cfg_backup_style eq "sync"){
1152 dev 351
	if ($cfg_clean_flag == 1){ # õÄÁÌÉÔØ ÓÔÁÒÙÅ ËÏÐÉÉ
1151 dev 352
	    print "WARNING: If you really shure to delete $cfg_local_path before sync operatioun uncomment line 'system( \"find \$cfg_local_path -not -path '\$cfg_local_path' -maxdepth 1 -exec \$prog_rm -rf \{\} \\;\");'" if ($cfg_verbose >= &VERB_ALL);
353
#    	    system( "find $cfg_local_path -not -path '$cfg_local_path' -maxdepth 1 -exec $prog_rm -rf \{\} \\;");
1149 dev 354
	}
355
 
356
	system( "cd $cfg_local_path; sh $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del");
357
	system( "$prog_tar -c -f - -T $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list| $prog_tar -xf - -C $cfg_local_path") == 0 || print "Local FS sync failed (tar|untar): $?\n";
358
	system( "cd $cfg_local_path; sh $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.dir");
359
	system( "cp -f $cfg_cache_dir/$cfg_backup_name/.hash $cfg_local_path/$backup_file_base.hash") == 0 || print "Local FS copy failed: $?\n";
360
 
361
    } else {
1152 dev 362
	if ($cfg_clean_flag == 1){ # õÄÁÌÉÔØ ÓÔÁÒÙÅ ËÏÐÉÉ
1149 dev 363
	    if ($cfg_save_old_backup == 0){
364
		system( "$prog_rm -f $cfg_local_path/*");
1152 dev 365
	    } else {
1149 dev 366
		if (! -d "$cfg_local_path/OLD"){
367
		    system( "mkdir $cfg_local_path/OLD");
368
		}
369
		system( "$prog_rm -f $cfg_local_path/OLD/*");
370
		system( "mv -f $cfg_local_path/$cfg_backup_name* $cfg_local_path/OLD/");
371
		# system( "$prog_rm -f $cfg_local_path/*");
372
	    }
373
	}
374
	system( "cp -f $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list $cfg_local_path/$backup_file_base.list") == 0 || print "Local FS .list copy failed: $?\n";
375
	system( "cp -f $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.dir $cfg_local_path/$backup_file_base.dir") == 0 || print "Local FS .dir copy failed: $?\n";
376
	system( "cp -f $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del $cfg_local_path/$backup_file_base.del") == 0 || print "Local FS .del copy failed: $?\n";
1152 dev 377
	system( "cp -f $cfg_cache_dir/$cfg_backup_name/.hash $cfg_local_path/$backup_file_base.hash") == 0 || print "Local FS .hash copy failed: $?\n";
378
	# ïÂÒÁÂÁÔÙ×ÁÅÍ ÒÁÚÂÉÅÎÉÅ ÎÁ ÔÏÍÁ
1149 dev 379
	for ($arc_block_level=0; $arc_block_level <= $#volume_position; $arc_block_level++){
1152 dev 380
	    my $tmp_list_file = crate_tmp_list($arc_block_level, $volume_position[$arc_block_level], $volume_position[$arc_block_level+1], "$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list");
1149 dev 381
	    system( "$prog_tar -c -f - -T $tmp_list_file $prog_gzip_filter $prog_pgp_filter > $cfg_local_path/$backup_file_base-$arc_block_level.tar${arc_ext}") == 0 || print "Local FS tar backup failed: $?\n";
382
	}
383
    }
384
 
385
} elsif ( $cfg_type eq "remote_ssh"){
386
    print "Storing remote ssh backup...\n" if ($cfg_verbose == &VERB_ALL);
387
    if ($cfg_backup_style eq "sync"){
1152 dev 388
	if ($cfg_clean_flag == 1){ # õÄÁÌÉÔØ ÓÔÁÒÙÅ ËÏÐÉÉ
1151 dev 389
	    system( "$prog_ssh -l $cfg_remote_login $cfg_remote_host find $cfg_remote_path -not -path '$cfg_remote_path' -maxdepth 1 -exec rm -rf \{\} \\;");
1149 dev 390
	}
391
	system( "cat $cfg_cache_dir/$cfg_backup_name/.hash | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/.hash'") == 0 || print "SSH connection failed (store .hash): $?\n";
392
	system( "cat $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/.del'") == 0 || print "SSH connection failed (store .hash): $?\n";
393
	system( "cat $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.dir | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/.dir'") == 0 || print "SSH connection failed (store .hash): $?\n";
394
        system("$prog_ssh -l $cfg_remote_login $cfg_remote_host '(cd $cfg_remote_path; sh .del)'");
395
        system( "$prog_tar -c -f - -T $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list $prog_gzip_filter| $prog_ssh -l $cfg_remote_login $cfg_remote_host tar -xf - -C $cfg_remote_path") == 0 || print "SSH connection failed (tar): $?\n";;
396
        system("$prog_ssh -l $cfg_remote_login $cfg_remote_host '(cd $cfg_remote_path; sh .dir)'");
397
 
398
 
399
	open (DEL, "<$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del");
400
	flock (DEL, 1);
401
	while(<DEL>){
402
	    chomp;
403
	    $cur_file = $_;
404
	    $cur_file =~ s/\'/\'\\\'\'/g;
405
    	    system("$prog_ssh -l $cfg_remote_login $cfg_remote_host rm -f '$cfg_remote_path/$cur_file'");
406
	}
407
	close(DEL);
408
    } else {
1152 dev 409
	if ($cfg_clean_flag == 1){ # õÄÁÌÉÔØ ÓÔÁÒÙÅ ËÏÐÉÉ
1149 dev 410
 
411
	    if ($cfg_save_old_backup == 0){
412
		system( "$prog_ssh -l $cfg_remote_login $cfg_remote_host rm -f $cfg_remote_path/*");
413
	    } else {
414
		system( "$prog_ssh -l $cfg_remote_login $cfg_remote_host '(if [ ! -d $cfg_remote_path/OLD ]; then mkdir $cfg_remote_path/OLD; fi)'");
415
		system( "$prog_ssh -l $cfg_remote_login $cfg_remote_host rm -f $cfg_remote_path/OLD/*");
416
		system( "$prog_ssh -l $cfg_remote_login $cfg_remote_host mv -f $cfg_remote_path/$cfg_backup_name* $cfg_remote_path/OLD/");
417
    		# system( "$prog_ssh -l $cfg_remote_login $cfg_remote_host rm -f $cfg_remote_path/*");
418
	    }
419
	}
420
	system( "cat $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/$backup_file_base.list'") == 0 || print "SSH connection failed (copy .list): $?\n";
421
	system( "cat $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.dir | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/$backup_file_base.dir'") == 0 || print "SSH connection failed (copy .dir): $?\n";
422
        system( "cat $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/$backup_file_base.del'") == 0 || print "SSH connection failed (copy .del): $?\n";
423
        system( "cat $cfg_cache_dir/$cfg_backup_name/.hash | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/$backup_file_base.hash'") == 0 || print "SSH connection failed (copy .hash): $?\n";
424
	system( "cat $cfg_cache_dir/$cfg_backup_name/.hash | $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/.hash'") == 0 || print "SSH connection failed (cache .hash): $?\n";
1152 dev 425
	# ïÂÒÁÂÁÔÙ×ÁÅÍ ÒÁÚÂÉÅÎÉÅ ÎÁ ÔÏÍÁ
1149 dev 426
	for ($arc_block_level=0; $arc_block_level <= $#volume_position; $arc_block_level++){
1152 dev 427
	    my $tmp_list_file = crate_tmp_list($arc_block_level, $volume_position[$arc_block_level], $volume_position[$arc_block_level+1], "$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list");
1149 dev 428
            system( "$prog_tar -c -f - -T $tmp_list_file $prog_gzip_filter $prog_pgp_filter| $prog_ssh -l $cfg_remote_login $cfg_remote_host 'cat - > $cfg_remote_path/$backup_file_base-$arc_block_level.tar${arc_ext}'") == 0 || print "SSH connection failed (tar): $?\n";
429
	}
430
    }
431
} elsif ( $cfg_type eq "remote_ftp"){
432
    print "Storing remote ftp backup...\n" if ($cfg_verbose == &VERB_ALL);
433
 
434
    if ($cfg_backup_style eq "sync"){
435
	print "WARNING: Backup style 'sync' only allowed for local and remote_ssh storage.\n" if ($cfg_verbose >= &VERB_ALL);
436
    } else {
1152 dev 437
	if ($cfg_clean_flag == 1){ # õÄÁÌÉÔØ ÓÔÁÒÙÅ ËÏÐÉÉ
1149 dev 438
	    if ($cfg_save_old_backup == 0){
439
		foreach $cur_dir ($ftp->ls()){
440
    		    $ftp->delete($cur_dir);
441
		}
442
	    } else {
443
		$ftp->mkdir("$cfg_remote_path/OLD");
444
		$ftp->cwd("$cfg_remote_path/OLD");
445
		foreach $cur_dir ($ftp->ls()){
446
    		    $ftp->delete($cur_dir);
447
		}
448
		$ftp->cwd("$cfg_remote_path");
449
		foreach $cur_dir ($ftp->ls()){
450
		    if ($cur_dir =~ /$cfg_backup_name/){
451
    			$ftp->rename($cur_dir,"$cfg_remote_path/OLD/$cur_dir");
452
		    }
453
		}
454
		foreach $cur_dir ($ftp->ls()){
455
    		    $ftp->delete($cur_dir);
456
		}
457
	    }
458
	}
459
	$ftp->delete("$backup_file_base.list");
460
	$ftp->put("$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list", "$backup_file_base.list") || print "Can't PUT .list file to remote FTP server\n";
461
	$ftp->delete("$backup_file_base.dir");
462
	$ftp->put("$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.dir", "$backup_file_base.dir")|| print "Can't PUT .dir file to remote FTP server\n";
463
	$ftp->delete("$backup_file_base.del");
464
	$ftp->put("$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del", "$backup_file_base.del")|| print "Can't PUT .del file to remote FTP server\n";
465
        $ftp->delete("$backup_file_base.hash");
466
        $ftp->put("$cfg_cache_dir/$cfg_backup_name/.hash", "$backup_file_base.hash")|| print "Can't PUT old .hash file to remote FTP server\n";
467
	$ftp->delete(".hash");
468
	$ftp->put("$cfg_cache_dir/$cfg_backup_name/.hash", ".hash")|| print "Can't PUT new .hash file to remote FTP server\n";
1152 dev 469
	# ïÂÒÁÂÁÔÙ×ÁÅÍ ÒÁÚÂÉÅÎÉÅ ÎÁ ÔÏÍÁ
1149 dev 470
	for ($arc_block_level=0; $arc_block_level <= $#volume_position; $arc_block_level++){
1152 dev 471
	    my $tmp_list_file = crate_tmp_list($arc_block_level, $volume_position[$arc_block_level], $volume_position[$arc_block_level+1], "$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list");
1149 dev 472
	    $ftp->delete("$backup_file_base-$arc_block_level.tar${arc_ext}");
473
	    open (TAR,"$prog_tar -c -f - -T $tmp_list_file $prog_gzip_filter $prog_pgp_filter|")|| print "tar failed: $?\n";
474
    	    flock(TAR,1);
475
	    $ftp->put(*TAR, "$backup_file_base-$arc_block_level.tar${arc_ext}")|| print "Can't store backup archive to remote FTP server.\n";
476
	    close(TAR);
477
	}
478
    	$ftp->quit;
479
    }
480
}
481
 
482
if ( $cfg_type eq "remote_ftp"){
483
    $ftp->quit;
484
}
485
print "***** Backup successful complete.\n" if ($cfg_verbose == &VERB_ALL);
486
exit (0);
487
 
488
 
489
########################################
490
sub add_to_backup{
491
  my($file_name, $file_dir, $md5_checksum_stat, $checksum_stat);
492
  my($tmp, $stat_mode, $stat_uid, $stat_gid, $stat_size, $stat_mtime, $stat_time);
493
 
494
  $file_name  = $_;
495
  $file_fullpath  = $File::Find::name;
496
  $file_dir  = $File::Find::dir;
497
  my $file_fullpath_esc = $file_fullpath;
498
  $file_fullpath_esc =~ s/\'/\'\\\'\'/g;
499
 
1152 dev 500
  # óÏÚÄÁÅÍ ÓÐÉÓÏË ÄÉÒÅËÔÏÒÉÊ
1151 dev 501
  if ((-d $file_fullpath) && (! -l $file_fullpath)){
1149 dev 502
      if (check_path($file_dir, $file_name) == 1){
503
	if ($cfg_backup_style ne "hash"){
1151 dev 504
	   ($tmp, $tmp, $stat_mode, $tmp, $stat_uid, $stat_gid, $tmp, $stat_size, $tmp, $stat_mtime, $stat_time) = stat($file_fullpath);
1149 dev 505
	    $stat_mode = sprintf ("%04o", $stat_mode & 07777);
506
	    $file_fullpath_esc =~ s/^\/(.*)$/$1/;
1152 dev 507
	    $stat_uid = getpwuid($stat_uid);
508
	    $stat_gid = getgrgid($stat_gid);
1149 dev 509
	    my ($sec,$min,$hour,$mday,$mon,$year) = localtime($stat_time);
510
	    $stat_time = sprintf ("%4.4d%2.2d%2.2d%2.2d%2.2d.%2.2d",
511
		                   $year+1900,$mon+1,$mday,$hour,$min,$sec);
1152 dev 512
    	    print DIRS "mkdir '$file_fullpath_esc'\n";
1149 dev 513
    	    print DIRS "chmod $stat_mode '$file_fullpath_esc'\n";
514
    	    print DIRS "chown $stat_uid:$stat_gid '$file_fullpath_esc'\n";
515
    	    print DIRS "touch -t $stat_time '$file_fullpath_esc'\n";
516
	    $cur_backup_size += int(length($file_fullpath)/100.0 + 1)*512;
517
	    if ($cfg_maximum_archive_size > 0 && $cur_backup_size + 10240 >= $cfg_maximum_archive_size){
518
	        my $old_val = $cur_backup_size - $stat_size - int(length($file_fullpath)/100.0 + 1)*512;
519
		my $tmp_pos= $#volume_position+1;
520
	        print "Volume $tmp_pos Done. Size: $old_val\n" if ($cfg_verbose == &VERB_ALL);
521
		$cur_backup_size = $stat_size + int(length($file_fullpath)/100.0 + 1)*512 + 1536;
522
	    	push @volume_position, $list_lines_cnt;
523
	    }
524
	}
525
      } else {
526
          if ($cfg_stopdir_prune == 1){
527
              $File::Find::prune = 1;
528
              return;
529
	  }
530
      }
1152 dev 531
  # òÁÂÏÔÁÅÍ Ó ÆÁÊÌÁÍÉ
1151 dev 532
  } elsif ((-f $file_fullpath) || (-l $file_fullpath)){
1149 dev 533
      if (check_path($file_dir, $file_name) == 1){
1151 dev 534
	  ($tmp, $tmp, $stat_mode, $tmp, $stat_uid, $stat_gid, $tmp, $stat_size, $tmp, $stat_mtime) = stat($file_fullpath);
1149 dev 535
	      $checksum_stat= md5_base64("$stat_mtime/$stat_size/$stat_mode/$stat_uid/$stat_gid");
536
	      # $file_fullpath_md5 = md5_base64($file_fullpath);
537
	      $file_fullpath_md5 = $file_fullpath;
538
	  if ($cfg_time_limit != 0 && $cur_time - $cfg_time_limit > $stat_mtime){
539
	      print "Time limit: $cur_time - $cfg_time_limit > $stat_mtime, file $file_fullpath ignored.\n" if ($cfg_verbose == &VERB_ALL);
540
	      next;
541
	  }
542
	  if ($cfg_size_limit != 0 && $cfg_size_limit < $stat_size){
543
	      print "Size limit: $cfg_size_limit < $stat_size, file $file_fullpath ignored.\n" if ($cfg_verbose == &VERB_ALL);
544
	      next;
545
	  }
546
 
1151 dev 547
	  if (($cfg_checksum eq "md5") && (! -l $file_fullpath)){
548
	      ($md5_checksum_stat, $tmp) = split(/\s+/, `$prog_md5sum '$file_fullpath_esc'`);
1149 dev 549
	      $active_hash_new{$file_fullpath_md5} = "$checksum_stat/$md5_checksum_stat";
550
	      check_update($file_fullpath, "$checksum_stat/$md5_checksum_stat", $file_fullpath_md5, $stat_size);
551
	  } else {
552
	      $active_hash_new{$file_fullpath} = $checksum_stat;
553
	      check_update($file_fullpath, $checksum_stat, $file_fullpath, $stat_size);
554
	  }
555
      }
556
  }
557
}
558
 
559
###############################################
1152 dev 560
# ðÒÏ×ÅÒÑÅÍ ÉÚÍÅÎÉÌÓÑ ÌÉ ÆÁÊÌ ÉÌÉ ÎÅÔ, ÅÓÌÉ ÄÁ ÁÐÄÅÊÔÉÍ ÌÏÇ.
1149 dev 561
sub check_update{
562
     my ($file, $checksum, $filesum, $stat_size) = @_;
563
 
1152 dev 564
    if ( $active_hash_last{$filesum} ne $checksum){
1149 dev 565
	if ($cfg_backup_style ne "hash"){
566
		$file =~ s/^\/(.*)$/$1/;
567
	        print LIST "$file\n";
568
 
1152 dev 569
	        # ïÂÒÁÂÁÔÙ×ÁÅÍ ÓÌÕÞÁÊ ÒÁÚÂÉÅÎÉÑ ÇÉÇÁÎÓËÉÈ ÁÒÈÉ×Ï×.
1149 dev 570
		if (-l "/$file"){
571
		    $stat_size = 0;
572
		}
573
	        $cur_backup_size += $stat_size + int(length($file)/100.0 + 1)*512;
574
#	  	print "$cur_backup_size:$stat_size:$file\n";
575
	        if ($cfg_maximum_archive_size > 0 && $cur_backup_size + 10240 >= $cfg_maximum_archive_size){
576
	        my $old_val = $cur_backup_size - $stat_size - int(length($file)/100.0 + 1)*512;
577
		my $tmp_pos= $#volume_position+1;
578
	        print "Volume $tmp_pos Done. Size: $old_val\n" if ($cfg_verbose == &VERB_ALL);
579
	        $cur_backup_size = $stat_size + int(length($file)/100.0 + 1)*512 + 1536;
580
	        push @volume_position, $list_lines_cnt;
581
	  }
582
 
583
	}
584
	$list_lines_cnt++;
585
    }
1152 dev 586
    delete $active_hash_last{$filesum};
587
    if (defined $dbobj_last){
588
	$dbobj_last->del($filesum);
1149 dev 589
    }
590
}
591
 
592
###############################################
1152 dev 593
# 0 - ÎÅ ÄÏÂÁ×ÌÑÔØ ÆÁÊÌ
594
# 1 - ÄÏÂÁ×ÔØ ÆÁÊÌ
1149 dev 595
 
596
sub check_path {
597
    my ($dir_name, $file_name) = @_;
598
    my ($item, $path);
599
 
600
    $path = "$dir_name/$file_name";
601
 
1151 dev 602
 
603
 
1149 dev 604
    foreach $item (@fs_notmask){
605
	if ($path =~ /$item/){
606
	    return 0;
607
	}
608
    }
609
 
610
    foreach $item (@fs_notfilemask){
611
	if ($file_name =~ /$item/){
612
	    return 0;
613
	}
614
    }
615
 
616
    foreach $item (@fs_filemask){
617
	if ($file_name =~ /$item/){
618
	    return 1;
619
	}
620
    }
621
 
622
    foreach $item (@fs_notdirmask){
623
	if ($dir_name =~ /$item/){
624
	    return 0;
625
	}
626
    }
627
 
628
 
629
    foreach $item (@fs_mask){
630
	if ($path =~ /$item/){
631
	    return 1;
632
	}
633
    }
634
 
635
    foreach $item (@fs_dirmask){
636
	if ($dir_name =~ /$item/){
637
	    return 1;
638
	}
639
    }
640
 
641
 
642
    foreach $item (@fs_notpath){
643
	if (($dir_name eq $item) || ($path eq $item) || ($dir_name =~ /^$item\//)){
644
	    return 0;
645
	}
646
    }
647
 
648
    return 1;
649
}
650
###############################################
1152 dev 651
# õÓÔÁÎÁ×ÌÉ×ÁÅÍ ÓÏÅÄÉÎÅÎÉÅ Ó ÕÄÁÌÅÎÎÙÍ ÓÅÒ×ÅÒÏÍ ÐÏ FTP.
1149 dev 652
 
653
sub ftp_connect{
654
    if ( $cfg_type eq "remote_ftp"){
1151 dev 655
	$ftp = Net::FTP->new($cfg_remote_host, Timeout => 30, Debug => 0) || die "Can't connect to ftp server.\n";
1149 dev 656
	$ftp->login($cfg_remote_login, $cfg_remote_password) || die "Can't login to ftp server.\n";
657
        $ftp->cwd($cfg_remote_path) || die "Path $cfg_remote_path not found on ftp server.\n";
658
	$ftp->binary();    
659
    }
660
}
661
###############################################
1152 dev 662
# óÏÄÁÎÉÅ ÓÐÉÓËÁ ÆÁÊÌÏ× ÄÌÑ ÐÏÍÅÝÅÎÉÑ × ÏÐÒÅÄÅÌÅÎÎÙÊ ÔÏÍ ÍÎÏÇÏÔÏÍÎÏÇÏ ÁÒÈÉ×Á.
1149 dev 663
 
1152 dev 664
sub crate_tmp_list{
1149 dev 665
	my ($arc_block_level, $position1, $position2, $full_list_path) = @_;
666
	my ($tmp_list_path, $pos_counter);
667
 
668
    if ($arc_block_level == 0 && $position1 == 0 && $position2 eq ''){
669
	$tmp_list_path = $full_list_path;
670
    } else {
671
	$pos_counter = 0;
672
	$tmp_list_path = "$full_list_path.$arc_block_level";
673
	open(FULL_LIST, "<$full_list_path")|| die "Can't open full list $full_list_path\n";
674
	flock(FULL_LIST, 1);
675
	open(TMP_LIST, ">$tmp_list_path")|| die "Can't create temp list $tmp_list_path\n";
676
	flock(TMP_LIST, 2);
677
	while(<FULL_LIST>){
678
	    if (($pos_counter >= $position1) && ($pos_counter < $position2 || $position2 eq '')){
679
		print TMP_LIST $_;
680
	    }
681
	    $pos_counter++;
682
	}
683
	close(TMP_LIST);
684
	close(FULL_LIST);
685
    }
686
    return $tmp_list_path;
687
}
688
###############################################
689
###############################################
690
 
691
__END__
692
 
693
=head1 NAME
694
 
695
fsbackup - file system backup and synchronization utility. 
696
 
697
=head1 SYNOPSIS
698
 
699
    fsbackup.pl [options] <configuration file>
700
 
701
=head1 DESCRIPTION
702
 
703
C<fsbackup.pl> is a incremental backup creation utility. 
704
C<fsbackup.pl> support backup compression and encryption. Backup can be stored
705
on local file system and on remote host stored over SSH or FTP. Some addition 
706
scripts allow backups SQL tables from PostgreSQL and MySQL (C<pgsql_backup.sh> 
707
and C<mysql_backup.sh>)), save system configuration files and list of installed 
708
packages (C<sysbackup.sh>). 
709
Backuped with C<fsbackup.pl> files can be recovered by script C<fsrestore.sh>,
710
backuped with C<sysbackup.sh> system packeges can be reinstalled by C<sysrestore.sh>
711
 
712
=head1 OPTIONS
713
 
714
The following command-line options can be used with C<fsbackup.pl>:
715
 
716
=over
717
 
718
=item C<-n>
719
 
720
Create new backup without checking files in previously stored hash.
721
 
722
=item C<-f>
723
 
724
Create full backup, like as C<-n> option.
725
 
726
=item C<-h>
727
 
728
Only rebuild hash, no storing files in backup archive.
729
 
730
=item C<-c>
731
 
732
Clean incremental backup storage and create new full backup without checking
733
$cfg_increment_level config parameter.
734
 
735
=head1 ADDITION SCRIPTS
736
 
737
=item C<create_backup.sh>
738
 
739
Backup planner running from C<crontab>. For example: 
740
 
1152 dev 741
18 4 * * * /usr/local/fsbackup/create_backup.sh
1149 dev 742
 
743
=item C<install.pl>
744
 
745
Script to install fsbackup package and some required perl modules.
746
 
747
=item C<fsbackup.pl>
748
 
749
File system backup utility.
750
 
751
=item C<cfg_example>
752
 
753
Example of configuration file.
754
 
755
=item C<scripts/pgsql_backup.sh>
756
 
757
=item C<scripts/mysql_backup.sh>
758
 
759
Script for backup SQL tables from PostreSQL and MySQL.
760
 
761
=item C<scripts/sysbackup.sh>
762
 
763
Script for store system configuration files and information about installed
764
packages.
765
 
766
=item C<scripts/fsrestore.sh>
767
 
768
Script for restore files backuped by C<fsbackup.pl>.
769
 
770
=item C<scripts/sysrestore.sh>
771
 
772
Script for reinstall packages stored by C<sysbackup.sh>.
773
 
774
 
775
=head1 CONFIGURATION FILE
776
 
777
=item B<$cfg_backup_name> = 'test_host'
778
 
779
Name of backup, single word.
780
 
1152 dev 781
=item B<$cfg_cache_dir> = '/usr/local/fsbackup/cache'
1149 dev 782
 
783
Path of internal cache directory for local backup method.
784
 
785
=item B<$prog_md5sum> = 'md5sum -b'
786
 
787
=item B<$prog_tar> = 'tar'
788
 
789
=item B<$prog_ssh> = 'ssh'
790
 
791
=item B<$prog_rm> = 'rm'
792
 
793
=item B<$prog_gzip> = 'gzip'
794
 
795
=item B<$prog_pgp> = 'gpg'
796
 
797
Full path of some external program running from C<fsbackup.pl>.
798
B<$prog_gzip = ''> - not use compression, B<$prog_pgp = ''> - not use 
799
encryption.
800
 
801
=item B<$cfg_checksum> = 'timesize'
802
 
803
File checksum method: 
804
 
805
timesize - checksum of file attributes (default, best speed) 
806
 
807
md5      - checksum of file attributes + MD5 checksum of file content.
808
 
809
=item B<$cfg_backup_style> = 'backup'
810
 
811
Backup style:
812
 
813
backup - incremental backup (copy only new and changed files).
814
 
815
full_backup - full backup (copy all files).	
816
 
817
sync - file tree synchronization.
818
 
819
hash - hash creation without storing archive (spying for new or changed files).
820
 
821
=item B<$cfg_increment_level> = 7
822
 
823
Incremental level (after how many incremental copy make full refresh of backup)
824
 
825
=item B<$cfg_type> = 'remote_ssh'
826
 
827
Type of backup storage:
828
 
829
    local  - store backup on local file system.
830
    remote_ssh - store backup on remote host over SSH connection.
831
    remote_ftp - store backup on remote FTP server.
832
 
833
 
834
=item B<$cfg_remote_host> = 'backup-server.test.ru'
835
 
836
=item B<$cfg_remote_login> = 'backup_login'
837
 
838
=item B<$cfg_remote_path> = '/home/backup_login/backup'
839
 
840
Connection parameters for remote_ssh storage type.
841
 
842
=item B<$cfg_remote_password> = 'Test1234'
843
 
844
Password of remote login for remote_ftp storage type.
845
 
846
=item B<$cfg_local_path> = '/var/backup/'
847
 
848
Path of directory to store backup on local file system for local storage type.
849
 
850
=item B<$cfg_time_limit> = 0
851
 
852
Limit of file creation time in days. If not 0, don't backup files created or 
853
modified later then $cfg_time_limit (days).
854
 
855
=item B<$cfg_size_limit> = 0
856
 
857
Limit of maximum file size. If not 0, don't backup files witch size more then 
858
$cfg_time_limit kilobytes.
859
 
860
=item B<$cfg_root_path> = '/'
861
 
862
Root path for initial chdir.
863
 
864
=item B<$cfg_pgp_userid> = ''
865
 
866
Name of user in public key ring with public key will be used for PGP encryption.
867
Not use encryption if not set.
868
 
869
=item B<$cfg_verbose> = 3
870
 
871
Verbose level.
872
 
873
 
874
    1	- Output errors and warnings.
875
    2	- Output all the  available  data.
876
 
877
=item B<$cfg_save_old_backup> = 1
878
 
879
Save previous backup to OLD directory before rotation or before storing full backup.
880
 
881
 
882
    1 - save old backup.
883
 
884
=item B<$cfg_maximum_archive_size> = 0
885
 
886
Size of maximum size (in KiloBytes) of single unpacked archive file (0 - unlimited file size).
887
 
888
=item B<$cfg_stopdir_prune> = 0
889
 
890
Recursive review of the prohibited directories.
891
 
892
    1 - not use a recursive entrance to directory prohibited for backup (speed is increased, reduces flexibility of customization).
893
 
894
=item B<__DATA__> - list of backuped path and regexp mask.
895
 
896
    /dir[/file] - backup file or directory.
897
    !/dir[/file] - NOT include this file or directory to backup.
898
    # - ignore this line.
899
 
900
Mask:
901
 
902
    =~ - regexp mask for include file or directory to backup.
903
    f~ - regexp file mask for include file to backup.
904
    d~ - regexp directory mask for include directory to backup.
905
    =! - regexp mask for NOT include file or directory to backup.
906
    f! - regexp file mask for NOT include file to backup.
907
    d! - regexp directory mask for NOT include directory to backup.
908
 
909
 
910
Operation priority:
911
 
912
    1. =!
913
    2. f!
914
    3. f~
915
    4. d!
916
    5. =~
917
    6. d~
918
    7. !path
919
    8. path
920
 
921
 
922
=head1 COPYRIGHT
923
 
924
Copyright (c) 2001 by Maxim Chirkov <mc@tyumen.ru>
925
http://www.opennet.ru/dev/fsbackup/
926
 
927
=head1 BUGS
928
 
929
Look TODO file.
930
 
931
=head1 AUTHORS
932
 
933
Maxim Chirkov <mc@tyumen.ru>
934
 
935
=cut