btrbk: add lockfile support, using perl "flock": add configuration option "lockfile <file>", and command line option "--lockfile"'

pull/93/head
Axel Burri 2016-06-07 16:17:02 +02:00
parent 6532229361
commit e4a7ba4be5
6 changed files with 57 additions and 3 deletions

View File

@ -1,5 +1,7 @@
btrbk-current btrbk-current
* Added "lockfile" configuration option and --lockfile command line
option (close: #81).
* Bugfix: raw targets: correctly handle multiple backups in same * Bugfix: raw targets: correctly handle multiple backups in same
target directory (close: #87). target directory (close: #87).
* Use relative instead of absolute binary calls in btrbk-mail. * Use relative instead of absolute binary calls in btrbk-mail.

30
btrbk
View File

@ -96,6 +96,7 @@ my %config_options = (
rate_limit => { default => undef, accept => [ "no" ], accept_regexp => qr/^[0-9]+[kmgt]?$/, require_bin => 'pv' }, rate_limit => { default => undef, accept => [ "no" ], accept_regexp => qr/^[0-9]+[kmgt]?$/, require_bin => 'pv' },
transaction_log => { default => undef, accept_file => { absolute => 1 } }, transaction_log => { default => undef, accept_file => { absolute => 1 } },
transaction_syslog => { default => undef, accept => \@syslog_facilities }, transaction_syslog => { default => undef, accept => \@syslog_facilities },
lockfile => { default => undef, accept_file => { absolute => 1 }, context => [ "root" ] },
raw_target_compress => { default => undef, accept => [ "no", "gzip", "bzip2", "xz" ] }, raw_target_compress => { default => undef, accept => [ "no", "gzip", "bzip2", "xz" ] },
raw_target_compress_level => { default => "default", accept => [ "default" ], accept_numeric => 1 }, raw_target_compress_level => { default => "default", accept => [ "default" ], accept_numeric => 1 },
@ -204,6 +205,7 @@ my $show_progress = 0;
my $err = ""; my $err = "";
my $abrt = ""; # last ABORTED() message my $abrt = ""; # last ABORTED() message
my $output_format; my $output_format;
my $lockfile;
my $tlog_fh; my $tlog_fh;
my $syslog_enabled = 0; my $syslog_enabled = 0;
my $current_transaction; my $current_transaction;
@ -3379,7 +3381,7 @@ MAIN:
@tm_now = localtime($start_time); @tm_now = localtime($start_time);
my %config_override_cmdline; my %config_override_cmdline;
my ($config_cmdline, $quiet, $verbose, $preserve_backups, $resume_only, $print_schedule); my ($config_cmdline, $quiet, $verbose, $preserve_backups, $resume_only, $print_schedule, $lockfile_cmdline);
unless(GetOptions( unless(GetOptions(
'help|h' => sub { VERSION_MESSAGE(); HELP_MESSAGE(0); exit 0; }, 'help|h' => sub { VERSION_MESSAGE(); HELP_MESSAGE(0); exit 0; },
'version' => sub { VERSION_MESSAGE(); exit 0; }, 'version' => sub { VERSION_MESSAGE(); exit 0; },
@ -3394,6 +3396,7 @@ MAIN:
'table|t' => sub { $output_format = "table" }, 'table|t' => sub { $output_format = "table" },
'format=s' => \$output_format, 'format=s' => \$output_format,
'print-schedule' => \$print_schedule, 'print-schedule' => \$print_schedule,
'lockfile=s' => \$lockfile_cmdline,
'override=s' => \%config_override_cmdline, # e.g. --override=incremental=no 'override=s' => \%config_override_cmdline, # e.g. --override=incremental=no
)) ))
{ {
@ -3535,6 +3538,15 @@ MAIN:
exit 2; exit 2;
} }
} }
if(defined($lockfile_cmdline)) {
if($lockfile_cmdline =~ /^($file_match)$/) {
$lockfile = $1; # untaint argument
} else {
ERROR "Option \"--lockfile\" is not a valid file name: \"$lockfile_cmdline\"";
HELP_MESSAGE(0);
exit 2;
}
}
INFO "$VERSION_INFO (" . localtime($start_time) . ")"; INFO "$VERSION_INFO (" . localtime($start_time) . ")";
@ -3637,6 +3649,22 @@ MAIN:
exit 2; exit 2;
} }
#
# try exclusive lock if set in config or command-line option
#
$lockfile //= config_key($config, "lockfile");
if(defined($lockfile) && (not $dryrun)) {
unless(open(LOCKFILE, ">>$lockfile")) {
# NOTE: the lockfile is never deleted by design
ERROR "Failed to open lock file '$lockfile': $!";
exit 3;
}
unless(flock(LOCKFILE, 6)) { # exclusive, non-blocking (LOCK_EX | LOCK_NB)
ERROR "Failed to take lock (another btrbk instance is running): $lockfile";
exit 3;
}
}
if($action_archive) if($action_archive)
{ {

View File

@ -56,6 +56,10 @@ snapshot_dir _btrbk_snap
#ssh_compression no #ssh_compression no
#ssh_cipher_spec default #ssh_cipher_spec default
# Enable lock file support: Ensures that only one instance of btrbk
# can be run at a time.
#lockfile /var/lock/btrbk.lock
# Don't wait for transaction commit on deletion. Set this to "after" # Don't wait for transaction commit on deletion. Set this to "after"
# or "each" to make sure the deletion of subvolumes is committed to # or "each" to make sure the deletion of subvolumes is committed to
# disk when btrbk terminates. # disk when btrbk terminates.

View File

@ -111,6 +111,8 @@ exitcode=$?
case $exitcode in case $exitcode in
0) status="All backups successful" 0) status="All backups successful"
;; ;;
3) status="Another instance of btrbk is running, no backup tasks performed!"
;;
10) status="ERROR: At least one backup task aborted!" 10) status="ERROR: At least one backup task aborted!"
;; ;;
*) status="ERROR: btrbk failed with error code $exitcode" *) status="ERROR: btrbk failed with error code $exitcode"

View File

@ -1,4 +1,4 @@
.TH "btrbk" "1" "2016-05-03" "btrbk v0.23.1" "" .TH "btrbk" "1" "2016-06-07" "btrbk v0.23.2-dev" ""
.\" disable hyphenation .\" disable hyphenation
.nh .nh
.\" disable justification (adjust text to left margin only) .\" disable justification (adjust text to left margin only)
@ -118,6 +118,14 @@ between different output formats.
Override a configuration option <config_option> with <value>. Override a configuration option <config_option> with <value>.
Globally, for ALL contexts. Use with care! Globally, for ALL contexts. Use with care!
.RE .RE
.PP
\-\-lockfile <file>
.RS 4
Create lockfile <file> on startup; checks lockfile before running any
btrfs commands (using perl "flock"), and exits if the lock is held by
another btrbk instance. Overrides configuration option
"lockfile". Ignored on dryrun (\fI\-n\fR, \fI\-\-dry\-run\fR).
.RE
.SH COMMANDS .SH COMMANDS
.PP .PP
.B run .B run
@ -324,6 +332,8 @@ No problems occurred.
Generic error code. Generic error code.
.IP "2" 4 .IP "2" 4
Parse error: when parsing command-line options or configuration file. Parse error: when parsing command-line options or configuration file.
.IP "3" 4
Lockfile error: if lockfile is present on startup.
.IP "10" 4 .IP "10" 4
Backup abort: At least one backup task aborted. Backup abort: At least one backup task aborted.
.IP "255" 4 .IP "255" 4

View File

@ -1,4 +1,4 @@
.TH "btrbk.conf" "5" "2016-05-03" "btrbk v0.23.1" "" .TH "btrbk.conf" "5" "2016-06-07" "btrbk v0.23.2-dev" ""
.\" disable hyphenation .\" disable hyphenation
.nh .nh
.\" disable justification (adjust text to left margin only) .\" disable justification (adjust text to left margin only)
@ -231,6 +231,14 @@ suffix of "k", "m", "g", or "t" can be added to denote kilobytes
(*1024), megabytes, and so on. Defaults to \[lq]no\[rq]. (*1024), megabytes, and so on. Defaults to \[lq]no\[rq].
.RE .RE
.PP .PP
\fBlockfile\fR <file>
.RS 4
Create lockfile <file> on startup; checks lockfile before running any
btrfs commands (using perl "flock"), and exits if the lock is held by
another btrbk instance. Ignored on dryrun (\fI\-n\fR,
\fI\-\-dry\-run\fR). See also \fI\-\-lockfile\fR command-line option.
.RE
.PP
\fBbtrfs_commit_delete\fR after|each|no \fBbtrfs_commit_delete\fR after|each|no
.RS 4 .RS 4
If set, make sure the deletion of snapshot and backup subvolumes are If set, make sure the deletion of snapshot and backup subvolumes are