-
Notifications
You must be signed in to change notification settings - Fork 1
/
brackup
executable file
·259 lines (189 loc) · 7.27 KB
/
brackup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#!/usr/bin/perl
# LICENCE INFORMATION
#
# This file is part of brackup-nn, a backup tool based on Brackup.
#
# Brackup is authored by Brad Fitzpatrick <[email protected]> (and others)
# and is copyright (c) Six Apart, Ltd, with portions copyright (c) Gavin Carr
# <[email protected]> (see code for details). Brackup is licensed for
# use, modification and/or distribution under the same terms as Perl itself.
#
# This file was forked from Brackup on 18 March 2013 and changed on and since
# this date by NewsNow Publishing Limited to effect bug fixes, reliability
# stability and/or performance improvements, and/or feature enhancements;
# and such changes are copyright (c) 2013 NewsNow Publishing Limited. You may
# use, modify, and/or redistribute brackup-nn under the same terms as Perl itself.
#
=head1 NAME
brackup - do a backup using Brackup
=head1 SYNOPSIS
$ brackup [-v] --from=<source> --to=<target> [--output=my_backup.brackup] [--save-stats]
=head2 OPTIONS
=over 4
=item --from=NAME
Required. The source or root of your backup. Must match a [SOURCE:NAME]
config section in your ~/.brackup.conf (which is auto-created for you
on first run, so then you just have to go modify it). See L<Brackup::Root>
for more.
=item --to=NAME
Required. The destination or target for your backup. Must match a
[TARGET:NAME] config section in your ~/.brackup.conf. See L<Brackup::Target>
for more.
=item --meta-dir=DIRECTORY
Optional. Defaults to the current directory.
The "metafile" index is saved here that you'll need to do a restore.
See also the I<local_meta_dir> target config entry, which is overridden by this argument.
=item --config=FILE
Specify the configuration file to use; defaults to ~/.brackup.
=item --save-stats[=FILE]
Optional. Flag to indicate that stats output should be recorded to a
file. If =FILE is omitted, defaults to "source-target-DATETIME.stats."
=item --verbose|-v
Show status during backup.
=item --dry-run|-n
Don't actually store any data on the target.
=item --du-stats
Prints the size, in kB, of data underneath each directory
(recursively) which will be backed up.
=item --zenityprogress
Produces output suitable for piping into C<zenity --progress> to get a
pretty GUI progress bar while running a backup. This option is
incompatable with C<--verbose>, as both print to STDOUT.
=item --list-sources
List the names of the sources defined in your configuration file.
=item --list-targets
List the names of the targets defined in your configuration file.
=item --allow-new-inv
By default, brackup aborts if it cannot find the inventory database,
as if it cannot find it because of some misconfiguration, it would
re-upload all the files.
When running brackup for the first time, use --allow-new-inv
to let it create a new inventory and continue.
=back
=head1 WARRANTY
Brackup is distributed as-is and comes without warranty of any kind,
expressed or implied. We aren't responsible for your data loss.
=head1 SEE ALSO
L<Brackup::Manual::Overview>
L<brackup-restore>
L<brackup-target>
L<Brackup::Root>
L<Brackup::Target>
=head1 AUTHOR
Brad Fitzpatrick E<lt>[email protected]<gt>
Copyright (c) 2006-2007 Six Apart, Ltd. All rights reserved.
This module is free software. You may use, modify, and/or redistribute this
software under the terms of same terms as perl itself.
=cut
use strict;
use warnings;
use Getopt::Long;
use Cwd;
use FindBin qw($Bin);
use lib "$Bin/lib";
use Brackup;
use Brackup::Util qw(noclobber_filename);
use File::Spec;
my ($src_name, $target_name, $meta_dir, $stats_file, $opt_help);
my $opt_dryrun;
my $opt_verbose;
my $opt_du_stats;
my $opt_zenityprogress;
my ($opt_list_sources, $opt_list_targets, $opt_allow_new_inv);
my $config_file = Brackup::Config->default_config_file_name;
my $arguments = join(' ', @ARGV);
usage() unless
GetOptions(
'from=s' => \$src_name,
'to=s' => \$target_name,
'verbose+' => \$opt_verbose,
'zenity-progress' => \$opt_zenityprogress,
'meta-dir=s' => \$meta_dir,
'save-stats:s' => \$stats_file,
'help' => \$opt_help,
'dry-run|n' => \$opt_dryrun,
'du-stats' => \$opt_du_stats,
'config=s' => \$config_file,
'list-sources' => \$opt_list_sources,
'list-targets' => \$opt_list_targets,
'allow-new-inv' => \$opt_allow_new_inv
);
usage() if @ARGV;
Brackup::Util::setup_sig_handlers();
if ($opt_help) {
eval "use Pod::Usage;";
Pod::Usage::pod2usage( -verbose => 1, -exitval => 0 );
exit 0;
}
if ($opt_verbose && $opt_zenityprogress) {
die "Can't use --verbose and --zenity-progress at the same time";
}
my $config = eval { Brackup::Config->load($config_file) } or
usage($@);
if ($opt_du_stats && $src_name) {
my $root = eval { $config->load_root($src_name); } or
die "Bogus --from name";
$root->du_stats;
exit 0;
}
if ($opt_list_sources) {
print join("\n", $config->list_sources), "\n";
exit 0;
}
if ($opt_list_targets) {
print join("\n", $config->list_targets), "\n";
exit 0;
}
usage() unless $src_name && $target_name;
my $cwd = getcwd();
sub usage {
my $why = shift || "";
if ($why) {
$why =~ s/\s+$//;
$why = "Error: $why\n\n";
}
die "${why}brackup --from=[source_name] --to=[target_name] [--output=<backup_metafile.brackup>]\nbrackup --help\n";
}
$|=1;
my $root = eval { $config->load_root($src_name); } or
usage($@);
my $target = eval { $config->load_target($target_name, allow_new_inv => $opt_allow_new_inv, verbose => $opt_verbose); } or
usage($@);
my $backup = Brackup::Backup->new(
root => $root,
target => $target,
dryrun => $opt_dryrun,
verbose => $opt_verbose,
zenityprogress => $opt_zenityprogress,
arguments => $arguments,
);
# Fix meta_dir (cwd will change, so we make $meta_dir default to it)
$meta_dir = $target->{local_meta_dir} unless defined $meta_dir;
$meta_dir = Brackup::Util->fix_meta_dir( $meta_dir, $cwd, 1 );
if (my ($stats, $backup_file, $error_returned) = eval { $backup->backup($meta_dir) }) {
if($error_returned){
warn "*** Backup interrupted by error '$error_returned'\n";
}else{
warn "Backup complete.\n" if $opt_verbose;
}
# Always print stats. They're terribly useful.
$stats->print;
if (defined $stats_file) {
if ($stats_file eq '') {
($stats_file = $backup_file) =~ s/(\.brackup)?$/.stats/;
}
else{
$stats_file = File::Spec->catfile($cwd, $stats_file) unless $stats_file =~ /^\//;
}
$stats_file = noclobber_filename($stats_file);
$stats->print($stats_file);
}
warn "Stats complete.\n" if $opt_verbose;
warn "Metafile written: '$backup_file'\n" if $opt_verbose && !$opt_dryrun;
Brackup::ProcManager->assert_all_reaped(); # This attempts to collect children
die "*** ERROR encountered during backup: '$error_returned'\n" if $error_returned;
exit 0;
} else {
warn "Error running backup: $@\n";
exit 1;
}