Subversion Repositories general

Rev

Rev 1253 | 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>
1258 dev 6
# Copyright (c) 2003-2006 by Anatoli Klassen. <anatoli@aksoft.net>
1149 dev 7
#
1258 dev 8
# Command line flags:
9
# -n - create a new (full) archive
10
# -c - delete old cache and create a full archive
1206 dev 11
#
12
# $Id: fsbackup.pl 1258 2006-07-14 12:50:58Z dev $
13
#
1149 dev 14
#############################################
1258 dev 15
use constant DB_DEF_CACHE_SIZE => 40960000; # size of cache in memory
1149 dev 16
 
17
use POSIX;
18
use File::Find;
19
use Digest::MD5 qw(md5_base64);
20
use DB_File;
1205 dev 21
use BSD::stat;
1149 dev 22
 
23
use constant VERB_SILENT => 0; # Silent mode, suspend all output.
1258 dev 24
use constant VERB_ERROR  => 1; # Output all errors and warnings.
25
use constant VERB_ALL    => 2; # Output all the available data.
1149 dev 26
 
1258 dev 27
my $version = "3.0";
1149 dev 28
my $list_lines_cnt = 0;
29
my $del_lines_cnt = 0;
30
my $cur_time = time();
31
my %active_hash_last;
32
my %active_hash_new;
33
my $cfg_new_flag = 0;
34
my $cfg_clean_flag = 0;
35
my $config = 0;
1258 dev 36
my $cur_backup_size = 1536; # tar block size, to calc volumes size
1149 dev 37
my $backup_file_base;
38
my $prog_gzip_filter;
39
my $cur_increment_level;
40
my $cur_dir;
41
my $cur_path;
42
my $cur_file;
43
my $cur_pathitem;
44
my $file_fullpath;
45
my $file_fullpath_md5;
46
my $key;
47
my $dbobj_new;
48
my $dbobj_last;
49
my $db_hashinfo;
50
my $db_hashinfo2;
51
my $file;
52
my @volume_position=(0);
1258 dev 53
my @fs_path=();        #  /dir[/file]
54
my @fs_notpath=();     #  !
55
my @fs_mask=();        #  =~
56
my @fs_filemask=();    #  f~
57
my @fs_dirmask=();     #  d~
58
my @fs_notmask=();     #  =!
59
my @fs_notfilemask=(); #  f!
60
my @fs_notdirmask=();  #  d!
1149 dev 61
 
1258 dev 62
# Load the config
63
if($ARGV[0] eq "-n" || $ARGV[0] eq "-c") {
64
  $config = $ARGV[1];
1149 dev 65
}
1258 dev 66
else {
67
  $config = $ARGV[0];
68
}
1149 dev 69
 
1258 dev 70
if(!-f $config) {
71
  die "Usage: fsbackup.pl [-n|-c] config_name\n";
1149 dev 72
}
73
 
74
require "$config";
75
 
1258 dev 76
$cfg_move_old_backup = 1 if(!defined($cfg_move_old_backup));
77
$cfg_exit_on_empty   = 1 if(!defined($cfg_exit_on_empty));
1154 dev 78
 
1258 dev 79
if(! -d $cfg_cache_dir) {
80
  die "\$cfg_cache_dir ($cfg_cache_dir) not found. Set \$cfg_cache_dir variable in fsbackup.pl\n";
1149 dev 81
}
82
 
1258 dev 83
# Convert config values
84
$cfg_time_limit           *= 60 * 60 * 24;
85
$cfg_size_limit           *= 1024;
86
$cfg_maximum_archive_size *= 1024;
1149 dev 87
 
1258 dev 88
# Command line args
89
if($ARGV[0] eq "-n" || $ARGV[0] eq "-c") {
90
  $cfg_new_flag = 1;
1149 dev 91
}
92
 
1258 dev 93
if($ARGV[0] eq "-c") {
94
  $cfg_clean_flag = 1;
1149 dev 95
}
96
 
1258 dev 97
# Check config
98
if($cfg_backup_name !~ /^[\w\d\_.]+$/) {
99
  die "Found illegal characters in $cfg_backup_name ($cfg_backup_name).";
1149 dev 100
}
101
 
1258 dev 102
if(!grep {$_ eq $cfg_checksum} ("md5", "timesize")) {
1149 dev 103
    die "Unknown checksum method:\$cfg_checksum=$cfg_checksum (allowed md5 or timesize)\n";
104
}
105
 
1258 dev 106
if(! -d $cfg_local_path) {
107
  die "Can't find \$cfg_local_path ($cfg_local_path)";
1149 dev 108
}
109
 
1258 dev 110
my($sec, $min, $hour, $mday, $mon, $year) = localtime($cur_time);
111
$backup_file_base = sprintf("%s-%4.4d.%2.2d.%2.2d.%2.2d.%2.2d.%2.2d",
112
  $cfg_backup_name, $year+1900, $mon+1, $mday, $hour, $min, $sec);
1149 dev 113
 
1258 dev 114
# Prepare
115
print "Creating $cfg_backup_name\n" if($cfg_verbose == &VERB_ALL);
1149 dev 116
 
1258 dev 117
chdir($cfg_root_path);
1149 dev 118
 
1258 dev 119
if(! -d "$cfg_cache_dir/$cfg_backup_name") {
120
  mkdir("$cfg_cache_dir/$cfg_backup_name", 0700);
1149 dev 121
}
122
 
1258 dev 123
# Calc increment level
124
if($cfg_increment_level != 0) {
125
  if(open(INCREMENT_LEVEL, "<$cfg_cache_dir/$cfg_backup_name/.increment_level")) {
126
    $cur_increment_level = <INCREMENT_LEVEL>;
127
    $cur_increment_level++;
128
    close(INCREMENT_LEVEL);
129
  }
130
  else {
131
    print "Can't open increment level file ($cfg_cache_dir/$cfg_backup_name/.increment_level).\n";
132
    $cur_increment_level = 0;
133
  }
1149 dev 134
 
1258 dev 135
  if($cur_increment_level >= $cfg_increment_level) {
136
    $cur_increment_level=0;
137
  }
1149 dev 138
 
1258 dev 139
  if($cur_increment_level == 0) {
140
    $cfg_new_flag   = 1;
141
    $cfg_clean_flag = 1;
142
  }
1149 dev 143
 
1258 dev 144
  if(open(INCREMENT_LEVEL, ">$cfg_cache_dir/$cfg_backup_name/.increment_level")) {
145
    print INCREMENT_LEVEL $cur_increment_level;
146
    close(INCREMENT_LEVEL);
147
  }
148
  else {
149
    print "Can't save increment level to file ($cfg_cache_dir/$cfg_backup_name/.increment_level).\n";
150
  }
151
  print "Current increment number: $cur_increment_level\n" if($cfg_verbose == &VERB_ALL);
1149 dev 152
}
153
 
1258 dev 154
# Load old cache
155
if(-f "$cfg_cache_dir/$cfg_backup_name/.hash" && $cfg_new_flag == 0) {
156
  rename("$cfg_cache_dir/$cfg_backup_name/.hash", "$cfg_cache_dir/$cfg_backup_name/.hash.last");
157
  $db_hashinfo = new DB_File::HASHINFO ;
158
  $db_hashinfo->{'cachesize'} =  DB_DEF_CACHE_SIZE;
159
  unless($dbobj_last = tie(%active_hash_last, "DB_File", "$cfg_cache_dir/$cfg_backup_name/.hash.last",
160
    O_RDWR|O_CREAT, 0644, $db_hashinfo))
161
  {
162
    print "WARNING: Error in hash, creating full backup.\n";
163
    unlink "$cfg_cache_dir/$cfg_backup_name/.hash.last";
164
  }
1149 dev 165
}
166
 
1258 dev 167
# Create new cache
1149 dev 168
unlink("$cfg_cache_dir/$cfg_backup_name/.hash");
169
$db_hashinfo2 = new DB_File::HASHINFO ;
1258 dev 170
$db_hashinfo2->{'cachesize'} = 100000;
171
$dbobj_new = tie(%active_hash_new, "DB_File", "$cfg_cache_dir/$cfg_backup_name/.hash",
172
  O_RDWR|O_CREAT, 0644, $db_hashinfo2) || print "Can't create or open DB File!\n";
1149 dev 173
 
1258 dev 174
# Save meta info
175
open(META, ">$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.meta")
176
  || print "Can't create meta file ($cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.meta).\n";
1154 dev 177
print META "fsbackup $version\n";
178
print META "increment level: $cur_increment_level\n";
179
close(META);
180
 
1258 dev 181
# Create list of files to save
182
open(LIST, ">$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list")
183
  || print "Can't create list file ($cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list).\n";
184
flock(LIST, 2);
1151 dev 185
 
1258 dev 186
# Load list of dirs and files to backup from the config
187
while(<DATA>) {
188
  chomp;
189
  if(/^\!(.*)$/) {           #  !
190
    push @fs_notpath, $1;
191
  }
192
  elsif(/^\=\~(.*)$/){       #  =~
193
    push @fs_mask, $1;
194
  }
195
  elsif(/^f\~(.*)$/){        #  f~
196
    push @fs_filemask, $1;
197
  }
198
  elsif(/^d\~(.*)$/){        #  d~
199
    push @fs_dirmask, $1;
200
  }
201
  elsif(/^\=\!(.*)$/){       #  =!
202
    push @fs_notmask, $1;
203
  }
204
  elsif(/^f\!(.*)$/){        #  f!
205
    push @fs_notfilemask, $1;
206
  }
207
  elsif(/^d\!(.*)$/){        #  d!
208
    push @fs_notdirmask, $1;
209
  }
210
  elsif(/^#/ || /^\s*$/){    #  comment
211
    next;
212
  }
213
  elsif(/[\/\w]+/) {         #  /dir[/file]
214
    push @fs_path, $_;
215
  }
216
  else {
217
    print STDERR "Syntax error: $_, ingnored.\n";
218
  }
219
}
1149 dev 220
 
1258 dev 221
# Find dirs and files to backup
222
foreach $cur_pathitem (@fs_path) {
223
  print "Adding $cur_pathitem ... " if($cfg_verbose == &VERB_ALL);
224
  find(\&add_to_backup, $cur_pathitem);
225
  print "done\n" if($cfg_verbose == &VERB_ALL);
1149 dev 226
}
1258 dev 227
close(LIST);
1149 dev 228
 
1258 dev 229
# Create list of deleted files and dirs
230
open(DEL, ">$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del")
231
  || print "Can't create list file ($cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del).\n";
232
flock (DEL, 2);
233
while(($file, $key) = each(%active_hash_last)) {
234
  $file =~ s/\'/\'\\\'\'/g;
235
  $file =~ s/^\/(.*)$/$1/;
236
  print DEL "rm -rf '$file'\n";
237
  $del_lines_cnt++;
1149 dev 238
}
1258 dev 239
close(DEL);
1149 dev 240
 
1258 dev 241
# Save the cache
1149 dev 242
$dbobj_new->sync();
243
untie %active_hash_new;
244
untie %active_hash_last;
245
 
1258 dev 246
# Goto root because all paths are without leading /
247
chdir("/");
1149 dev 248
 
1258 dev 249
# Tar them
250
if($cfg_exit_on_empty == 1 && $list_lines_cnt == 0 && $del_lines_cnt == 0) {
251
  print "WARNING: Nothing to backup.\n";
252
  exit;
1149 dev 253
}
1258 dev 254
 
255
print "Storing local backup\n" if($cfg_verbose == &VERB_ALL);
256
if($cfg_clean_flag == 1) {        # delete old backup
257
  if($cfg_save_old_backup == 0) {
258
    system("$prog_rm -f $cfg_local_path/*");
259
  }
260
  elsif($cfg_move_old_backup == 1) {
261
    system("mkdir $cfg_local_path/OLD") if(!-d "$cfg_local_path/OLD");
262
    system("$prog_rm -f $cfg_local_path/OLD/*");
263
    system("mv -f $cfg_local_path/$cfg_backup_name* $cfg_local_path/OLD/");
264
  }
1149 dev 265
}
1258 dev 266
system("cp -f $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.meta $cfg_local_path/$backup_file_base.meta")
267
  == 0 || print "Local FS .meta copy failed: $?\n";
268
system("cp -f $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list $cfg_local_path/$backup_file_base.list")
269
  == 0 || print "Local FS .list copy failed: $?\n";
270
system("cp -f $cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.del $cfg_local_path/$backup_file_base.del")
271
  == 0 || print "Local FS .del copy failed: $?\n";
1149 dev 272
 
1258 dev 273
# Split to volumes
274
for($arc_block_level = 0; $arc_block_level <= $#volume_position; $arc_block_level++) {
275
  my $tmp_list_file = create_tmp_list($arc_block_level, $volume_position[$arc_block_level],
276
    $volume_position[$arc_block_level+1], "$cfg_cache_dir/$cfg_backup_name/$cfg_backup_name.list");
277
  system("$prog_tar -c -f - -n -z -T $tmp_list_file > $cfg_local_path/$backup_file_base-$arc_block_level.tar.gz") == 0 || print "Local FS tar backup failed: $?\n";
1149 dev 278
}
279
 
1258 dev 280
print "***** Backup successful complete.\n" if($cfg_verbose == &VERB_ALL);
1149 dev 281
exit (0);
282
 
283
########################################
1253 dev 284
sub add_to_backup
285
{
286
  my($file_name, $file_dir, $md5_checksum_stat, $checksum_stat, $file_fullpath_esc);
1258 dev 287
  my($tmp, $stat_mode, $stat_uid, $stat_gid, $stat_size, $stat_time, $stat_flags);
1149 dev 288
 
1253 dev 289
  $file_name         = $_;
290
  $file_fullpath     = $File::Find::name;
291
  $file_dir          = $File::Find::dir;
292
  $file_fullpath_esc = $file_fullpath;
1149 dev 293
  $file_fullpath_esc =~ s/\'/\'\\\'\'/g;
294
 
1258 dev 295
  # dir
296
  if((-d $file_fullpath) && (!-l $file_fullpath)) {
1253 dev 297
    if(check_path($file_dir, $file_name) == 1) {
1258 dev 298
      ($tmp, $tmp, $stat_mode, $tmp, $stat_uid, $stat_gid, $tmp, $stat_size, $tmp, $tmp,
299
        $stat_time, $tmp, $tmp, $tmp, $tmp, $tmp, $stat_flags, $tmp) = lstat($file_fullpath);
300
      $checksum_stat     = md5_base64("$stat_time/$stat_mode/$stat_uid/$stat_gid");
301
      $file_fullpath_esc =~ s/^\/(.*)$/$1/;
1228 dev 302
 
1258 dev 303
      $active_hash_new{$file_fullpath} = "D $checksum_stat";
304
      check_update($file_fullpath, "D $checksum_stat", $file_fullpath, $stat_size);
305
 
306
      if($stat_flags & UF_NODUMP) {
307
        push @fs_notpath, "$file_dir/$file_name"; # if nodump - skip all subitems
308
        if($cfg_stopdir_prune == 1) {
309
          $File::Find::prune = 1;
310
          return;
1253 dev 311
        }
1149 dev 312
      }
1253 dev 313
    }
314
    else {
315
      if($cfg_stopdir_prune == 1) {
316
        $File::Find::prune = 1;
317
        return;
318
      }
319
    }
320
  }
1258 dev 321
  # file or symlink
1253 dev 322
  elsif((-f $file_fullpath) || (-l $file_fullpath)) {
323
    if(check_path($file_dir, $file_name) == 1) {
1258 dev 324
      ($tmp, $tmp, $stat_mode, $tmp, $stat_uid, $stat_gid, $tmp, $stat_size, $tmp, $tmp,
1253 dev 325
        $stat_time, $tmp, $tmp, $tmp, $tmp, $tmp, $stat_flags, $tmp) = lstat($file_fullpath);
326
      unless($stat_flags & UF_NODUMP) {
1258 dev 327
        $checksum_stat     = md5_base64("$stat_time/$stat_size/$stat_mode/$stat_uid/$stat_gid");
1253 dev 328
        $file_fullpath_md5 = $file_fullpath;
1258 dev 329
 
330
        if($cfg_time_limit != 0 && $cur_time - $cfg_time_limit > $stat_time) {
331
          print "Time limit: $cur_time - $cfg_time_limit > $stat_time, file $file_fullpath ignored.\n"
1253 dev 332
            if($cfg_verbose == &VERB_ALL);
333
          next;
334
        }
335
        if($cfg_size_limit != 0 && $cfg_size_limit < $stat_size) {
336
          print "Size limit: $cfg_size_limit < $stat_size, file $file_fullpath ignored.\n"
337
            if($cfg_verbose == &VERB_ALL);
338
          next;
339
        }
1149 dev 340
 
1253 dev 341
        if(($cfg_checksum eq "md5") && (! -l $file_fullpath)) {
342
          ($md5_checksum_stat, $tmp) = split(/\s+/, `$prog_md5sum '$file_fullpath_esc'`);
1258 dev 343
          $active_hash_new{$file_fullpath_md5} = "F $checksum_stat/$md5_checksum_stat";
344
          check_update($file_fullpath, "F $checksum_stat/$md5_checksum_stat", $file_fullpath_md5, $stat_size);
1205 dev 345
        }
1258 dev 346
        else {
347
          $active_hash_new{$file_fullpath} = "F $checksum_stat";
348
          check_update($file_fullpath, "F $checksum_stat", $file_fullpath, $stat_size);
349
        }
1253 dev 350
      }
1205 dev 351
    }
1253 dev 352
  }
1149 dev 353
}
354
 
355
###############################################
1258 dev 356
# Check if file was updated
357
sub check_update
358
{
359
  my($file, $checksum, $filesum, $stat_size) = @_;
1149 dev 360
 
1258 dev 361
  if($active_hash_last{$filesum} ne $checksum) {
362
    $file =~ s/^\/(.*)$/$1/;
363
    print LIST "$file\n";
364
 
365
    $stat_size = 0 if(-l "/$file");
366
 
367
    # next volume
368
    $cur_backup_size += $stat_size + int(length($file)/100.0 + 1)*512;
369
    if($cfg_maximum_archive_size > 0 && $cur_backup_size + 10240 >= $cfg_maximum_archive_size) {
370
      my $old_val = $cur_backup_size - $stat_size - int(length($file)/100.0 + 1)*512;
371
      my $tmp_pos = $#volume_position+1;
372
      print "Volume $tmp_pos Done. Size: $old_val\n" if ($cfg_verbose == &VERB_ALL);
373
      $cur_backup_size = $stat_size + int(length($file)/100.0 + 1)*512 + 1536;
374
      push @volume_position, $list_lines_cnt;
375
    }
376
    $list_lines_cnt++;
377
  }
1149 dev 378
 
1258 dev 379
  if($active_hash_last{$filesum} && substr($active_hash_last{$filesum}, 0, 1) ne substr($checksum, 0, 1)) {
380
    # if old entry was a directory and now it's file or link or vice versa, leave it in hash 
381
    # to add it later to the delete list
382
  }
383
  else {
384
    delete $active_hash_last{$filesum};
385
    $dbobj_last->del($filesum) if(defined $dbobj_last);
386
  }
1149 dev 387
}
388
 
389
###############################################
1258 dev 390
# 0 - don't add the file
391
# 1 - add the file
392
sub check_path
393
{
394
  my ($dir_name, $file_name) = @_;
395
  my ($item, $path);
1149 dev 396
 
1258 dev 397
  $path = "$dir_name/$file_name";
1149 dev 398
 
1258 dev 399
  foreach $item (@fs_notmask) {
400
    return 0 if($path =~ /$item/);
401
  }
1151 dev 402
 
1258 dev 403
  foreach $item (@fs_notfilemask) {
404
    return 0 if($file_name =~ /$item/);
405
  }
1151 dev 406
 
1258 dev 407
  foreach $item (@fs_filemask) {
408
    return 1 if($file_name =~ /$item/);
409
  }
1149 dev 410
 
1258 dev 411
  foreach $item (@fs_notdirmask) {
412
    return 0 if($dir_name =~ /$item/);
413
  }
1149 dev 414
 
1258 dev 415
  foreach $item (@fs_mask) {
416
    return 1 if($path =~ /$item/);
417
  }
1149 dev 418
 
1258 dev 419
  foreach $item (@fs_dirmask) {
420
    return 1 if($dir_name =~ /$item/);
421
  }
1149 dev 422
 
1258 dev 423
  foreach $item (@fs_notpath) {
424
    return 0 if(($dir_name eq $item) || ($path eq $item) || ($dir_name =~ /^$item\//));
425
  }
1149 dev 426
 
1258 dev 427
  return 1;
428
}
1149 dev 429
 
430
###############################################
1258 dev 431
# Split the big list into volume list
432
sub create_tmp_list
433
{
434
  my($arc_block_level, $position1, $position2, $full_list_path) = @_;
435
  my($tmp_list_path, $pos_counter);
1149 dev 436
 
1258 dev 437
  if($arc_block_level == 0 && $position1 == 0 && $position2 eq '') {
438
    $tmp_list_path = $full_list_path;
439
  }
440
  else {
441
    $pos_counter = 0;
442
    $tmp_list_path = "$full_list_path.$arc_block_level";
443
    open(FULL_LIST, "<$full_list_path") || die "Can't open full list $full_list_path\n";
444
    flock(FULL_LIST, 1);
445
    open(TMP_LIST, ">$tmp_list_path") || die "Can't create temp list $tmp_list_path\n";
446
    flock(TMP_LIST, 2);
447
    while(<FULL_LIST>) {
448
      print TMP_LIST $_ if(($pos_counter >= $position1) && ($pos_counter < $position2 || $position2 eq ''));
449
      $pos_counter++;
1149 dev 450
    }
1258 dev 451
    close(TMP_LIST);
452
    close(FULL_LIST);
453
  }
454
  return $tmp_list_path;
1149 dev 455
}
456
 
457
###############################################
458
###############################################
459
 
460
__END__
461
 
462
=head1 NAME
463
 
464
fsbackup - file system backup and synchronization utility. 
465
 
466
=head1 SYNOPSIS
467
 
468
    fsbackup.pl [options] <configuration file>
469
 
470
=head1 DESCRIPTION
471
 
472
C<fsbackup.pl> is a incremental backup creation utility. 
1258 dev 473
C<fsbackup.pl> support backup compression and encryption. Some addition 
1149 dev 474
scripts allow backups SQL tables from PostgreSQL and MySQL (C<pgsql_backup.sh> 
475
and C<mysql_backup.sh>)), save system configuration files and list of installed 
476
packages (C<sysbackup.sh>). 
477
Backuped with C<fsbackup.pl> files can be recovered by script C<fsrestore.sh>,
478
backuped with C<sysbackup.sh> system packeges can be reinstalled by C<sysrestore.sh>
479
 
480
=head1 OPTIONS
481
 
482
The following command-line options can be used with C<fsbackup.pl>:
483
 
484
=over
485
 
486
=item C<-n>
487
 
488
Create new backup without checking files in previously stored hash.
489
 
490
=item C<-f>
491
 
492
Create full backup, like as C<-n> option.
493
 
494
=item C<-h>
495
 
496
Only rebuild hash, no storing files in backup archive.
497
 
498
=item C<-c>
499
 
500
Clean incremental backup storage and create new full backup without checking
501
$cfg_increment_level config parameter.
502
 
503
=head1 ADDITION SCRIPTS
504
 
505
=item C<create_backup.sh>
506
 
507
Backup planner running from C<crontab>. For example: 
508
 
1154 dev 509
18 4 * * * /root/backup/fsbackup/create_backup.sh
1149 dev 510
 
511
=item C<install.pl>
512
 
513
Script to install fsbackup package and some required perl modules.
514
 
515
=item C<fsbackup.pl>
516
 
517
File system backup utility.
518
 
519
=item C<cfg_example>
520
 
521
Example of configuration file.
522
 
523
=item C<scripts/pgsql_backup.sh>
524
 
525
=item C<scripts/mysql_backup.sh>
526
 
527
Script for backup SQL tables from PostreSQL and MySQL.
528
 
529
=item C<scripts/sysbackup.sh>
530
 
531
Script for store system configuration files and information about installed
532
packages.
533
 
534
=item C<scripts/fsrestore.sh>
535
 
536
Script for restore files backuped by C<fsbackup.pl>.
537
 
538
=item C<scripts/sysrestore.sh>
539
 
540
Script for reinstall packages stored by C<sysbackup.sh>.
541
 
542
 
543
=head1 CONFIGURATION FILE
544
 
545
=item B<$cfg_backup_name> = 'test_host'
546
 
547
Name of backup, single word.
548
 
1154 dev 549
=item B<$cfg_cache_dir> = '/root/backup/fsbackup/cache'
1149 dev 550
 
551
Path of internal cache directory for local backup method.
552
 
553
=item B<$prog_md5sum> = 'md5sum -b'
554
 
555
=item B<$prog_tar> = 'tar'
556
 
557
=item B<$prog_rm> = 'rm'
558
 
559
=item B<$cfg_checksum> = 'timesize'
560
 
561
File checksum method: 
562
 
563
timesize - checksum of file attributes (default, best speed) 
564
 
565
md5      - checksum of file attributes + MD5 checksum of file content.
566
 
567
=item B<$cfg_increment_level> = 7
568
 
569
Incremental level (after how many incremental copy make full refresh of backup)
570
 
571
=item B<$cfg_local_path> = '/var/backup/'
572
 
573
Path of directory to store backup on local file system for local storage type.
574
 
575
=item B<$cfg_time_limit> = 0
576
 
577
Limit of file creation time in days. If not 0, don't backup files created or 
578
modified later then $cfg_time_limit (days).
579
 
580
=item B<$cfg_size_limit> = 0
581
 
582
Limit of maximum file size. If not 0, don't backup files witch size more then 
583
$cfg_time_limit kilobytes.
584
 
585
=item B<$cfg_root_path> = '/'
586
 
587
Root path for initial chdir.
588
 
589
=item B<$cfg_verbose> = 3
590
 
591
Verbose level.
592
 
1258 dev 593
 
594
    1 - Output errors and warnings.
595
    2 - Output all the  available  data.
1149 dev 596
 
597
=item B<$cfg_save_old_backup> = 1
598
 
599
Save previous backup to OLD directory before rotation or before storing full backup.
600
 
601
 
602
    1 - save old backup.
603
 
604
=item B<$cfg_maximum_archive_size> = 0
605
 
606
Size of maximum size (in KiloBytes) of single unpacked archive file (0 - unlimited file size).
607
 
608
=item B<$cfg_stopdir_prune> = 0
609
 
610
Recursive review of the prohibited directories.
611
 
612
    1 - not use a recursive entrance to directory prohibited for backup (speed is increased, reduces flexibility of customization).
613
 
614
=item B<__DATA__> - list of backuped path and regexp mask.
615
 
616
    /dir[/file] - backup file or directory.
617
    !/dir[/file] - NOT include this file or directory to backup.
618
    # - ignore this line.
619
 
620
Mask:
621
 
622
    =~ - regexp mask for include file or directory to backup.
623
    f~ - regexp file mask for include file to backup.
624
    d~ - regexp directory mask for include directory to backup.
625
    =! - regexp mask for NOT include file or directory to backup.
626
    f! - regexp file mask for NOT include file to backup.
627
    d! - regexp directory mask for NOT include directory to backup.
628
 
629
 
630
Operation priority:
631
 
632
    1. =!
633
    2. f!
634
    3. f~
635
    4. d!
636
    5. =~
637
    6. d~
638
    7. !path
639
    8. path
640
 
641
 
642
=head1 COPYRIGHT
643
 
644
Copyright (c) 2001 by Maxim Chirkov <mc@tyumen.ru>
645
http://www.opennet.ru/dev/fsbackup/
646
 
1258 dev 647
Copyright (c) 2003-2006 by Anatoli Klassen. <anatoli@aksoft.net>
648
http://www.26th.net/public/projects/fsbackup/
649
 
1149 dev 650
=head1 BUGS
651
 
652
Look TODO file.
653
 
654
=head1 AUTHORS
655
 
656
Maxim Chirkov <mc@tyumen.ru>
1258 dev 657
Anatoli Klassen <anatoli@aksoft.net>
1149 dev 658
 
659
=cut