--- a/.hgignore Tue Oct 27 21:31:07 2009 +0100
+++ b/.hgignore Tue Oct 27 22:32:42 2009 +0100
@@ -1,1 +1,1 @@
-py2b.conf
+ftbackup.conf
--- a/ftbackup Tue Oct 27 21:31:07 2009 +0100
+++ b/ftbackup Tue Oct 27 22:32:42 2009 +0100
@@ -29,6 +29,7 @@
my $opt_verbose = 0;
my $opt_dry = 0;
my $opt_force = 0;
+my $opt_label = "daily";
sub get_configs(@);
sub get_candidates();
@@ -39,59 +40,60 @@
$SIG{INT} = sub { warn "Got signal INT\n"; exit 1 };
my %CONFIG = (
- FTP_DIR => "backup/daily/$NODE",
+ FTP_DIR => "backup/<LABEL>/<NODE>",
FTP_PASSIVE => 1,
- FULL_CYCLE => 7, # not used
+ FULL_CYCLE => 7, # not used yet
);
MAIN: {
+ Getopt::Long::Configure("bundling");
GetOptions(
"l|level=i" => \$opt_level,
+ "L|label=s" => \$opt_label,
"d|debug:s" => sub { push @opt_debug, split /,/, $_[1] },
- "h|help" => sub { pod2usage(-exit => 0, -verbose => 1) },
- "m|man" => sub { pod2usage(-exit => 0, -verbose => 3) },
"v|verbose" => \$opt_verbose,
"dry" => \$opt_dry,
"f|force" => \$opt_force,
+ "h|help" => sub { pod2usage(-exit => 0, -verbose => 1) },
+ "m|man" => sub { pod2usage(-exit => 0, -verbose => 3) },
) or pod2usage;
+
my %cf = (%CONFIG, get_configs(@CONFIGS));
+ $cf{FTP_DIR} =~ s/<NODE>/$NODE/g;
+ $cf{FTP_DIR} =~ s/<LABEL>/$opt_label/g;
my @dev = get_candidates();
- ### current candiates: @dev
+ ### %cf
+ ### @dev
my $ftp = new FTP($cf{FTP_HOST},
Passive => $cf{FTP_PASSIVE},
Debug => @opt_debug ~~ /^ftp$/) or die $@;
$ftp->login or die $ftp->message;
+ $ftp->home($ftp->try(pwd => ()));
$ftp->try(binary => ());
$ftp->try(mkpath => $cf{FTP_DIR});
$ftp->try(cwd => $cf{FTP_DIR});
- given ($opt_level) {
- when(0) {
- $ftp->try(mkpath => $opt_today);
- $ftp->try(cwd => $opt_today);
- }
- default {
- # find the last full backup directory
- my $last_full = (reverse sort grep /^\d{4}-\d{2}-\d{2}$/, $ftp->ls)[0];
- die "no last full backup found in @{[$ftp->pwd]}\n"
- if not $last_full;
- $ftp->try(cwd => $last_full);
- }
- }
-
- # now sitting inside the directory for the last full backup
- verbose "Now in @{[$ftp->pwd]}.\n";
+ ### @dev
# and now we can start doing something with our filesystems
- foreach my $dev (@dev) {
+ DEVICE: foreach my $dev (@dev) {
+ my $dir = $dev->{mountpoint};
+ $dir =~ s/_/__/g;
+ $dir =~ s/\//_/g;
+ $dir = "$cf{FTP_DIR}/$dir";
- my $file = basename($dev->{dev}) . "."
- . strftime("%F_%R", localtime $NOW)
- . ".$opt_level.ssl";
+ $ftp->home();
+ $ftp->try(mkpath => $dir);
+ $ftp->try(cwd => $dir);
+
+ verbose "Now in @{[$ftp->pwd]}.\n";
+
+ my $file = strftime("%F_%R", localtime $NOW)
+ . ".$opt_level";
my $label = "$NODE:" . basename($dev->{rdev});
- verbose "Working on $dev->{dev} as $dev->{rdev}, stored as $file\n";
+ verbose "Working on $dev->{dev} as $dev->{rdev} on $dev->{mountpoint}, stored as $file\n";
next if $opt_dry;
## complain if there is already a full backup in this
@@ -115,7 +117,7 @@
(my $device) = (grep /lv name/i, `lvdisplay $snap`)[0] =~ /(\S+)\s*$/;
- system($_ = "fsck -f -C0 -y $device");
+ system($_ = "fsck -f @{[$opt_verbose ? '-C0' : '']} -y $device");
warn "fsck on $device (using: $_) failed\n" if $?;
($dev->{dump}) = $device;
@@ -239,6 +241,8 @@
use warnings;
use base qw(Net::FTP);
+ my %data;
+
sub new {
my $class = shift;
return bless Net::FTP->new(@_) => $class;
@@ -262,17 +266,26 @@
}
$self->cwd($current);
}
+
+ sub home {
+ my $self = shift;
+ return $data{ref $self}{home} = shift if @_;
+ $self->try(cwd => exists $data{ref $self}{home} ? $data{ref $self}{home} : "/");
+ return $self->pwd();
+ }
+
+ sub get_home { return $data{ref shift}{home} };
}
__END__
=head1 NAME
-py2b - backup tool
+ftbackup - ftp backup tool
=head1 SYNOPSIS
- py2b [--level <level>] [options]
+ ftbackup [--level <level>] [options]
=head1 OPTIONS
@@ -297,6 +310,10 @@
The backup level. Level other than "0" needs a previous
level 0 (full) backup. (default: 0)
+=item B<-L>|B<--label> I<label>
+
+The label for the backup. (default: daily)
+
=item B<-v>|B<--verbose>
Be verbose. (default: no)
@@ -307,9 +324,9 @@
The config files are searched in the following places:
- /etc/py2b
- ~/.py2b
- ./py2b.conf
+ /etc/ftbackup
+ ~/.ftbackup
+ ./ftbackup.conf
If the location is a directory, all (not hidden) files in this directory are
considered to be config, if the location a file itself, this is considered to