btrbk: parse stderr from send/receive commands (error on /^ERROR/), as "btrfs receive" returns 0 even if nothing is received.

pull/57/head
Axel Burri 2015-10-20 22:05:02 +02:00
parent da86557b89
commit f526d454f7
2 changed files with 38 additions and 5 deletions

View File

@ -17,6 +17,7 @@ btrbk-current
* Bugfix: correctly handle "incremental no" option.
* Bugfix: return exit status 10 instead of 0 if one or more backup
tasks aborted.
* Better error handling for send/receive commands (close: #33).
* Hardened ssh_filter_btrbk.sh script: fine-grained access control,
restrict-path option, sudo option (close: #45).

42
btrbk
View File

@ -331,7 +331,6 @@ sub run_cmd(@)
$cmd .= $pipe . $_->{cmd_text};
$pipe = ' | ';
if($_->{catch_stderr}) {
$cmd .= ' 2>&1';
$catch_stderr = 1;
$filter_stderr = $_->{filter_stderr};
}
@ -344,6 +343,14 @@ sub run_cmd(@)
}
DEBUG "### $cmd";
if($catch_stderr) {
if(scalar(@commands) == 1) {
$cmd .= ' 2>&1';
} else {
$cmd = '{ ' . $cmd . ' ; } 2>&1';
}
}
my $ret = "";
$ret = `$cmd`;
chomp($ret);
@ -1220,8 +1227,8 @@ sub btrfs_send_receive($$$$)
my @send_options;
my @receive_options;
push(@send_options, '-p', $parent_path) if($parent_path);
push(@send_options, '-v') if($loglevel >= 3);
push(@receive_options, '-v') if($loglevel >= 3);
# push(@send_options, '-v') if($loglevel >= 3);
# push(@receive_options, '-v') if($loglevel >= 3);
my @cmd_pipe;
push @cmd_pipe, {
@ -1236,16 +1243,41 @@ sub btrfs_send_receive($$$$)
cmd => [ qw(btrfs receive), @receive_options, $target_path . '/' ],
rsh => $target->{RSH},
name => "btrfs receive",
catch_stderr => 1, # hack for shell-based run_cmd()
filter_stderr => sub { $err = $_; $_ = undef }
};
my $send_receive_error = 0;
start_transaction("send-receive",
vinfo_prefixed_keys("target", $vol_received),
vinfo_prefixed_keys("source", $snapshot),
vinfo_prefixed_keys("parent", $parent),
);
my $ret = run_cmd(@cmd_pipe);
end_transaction("send-receive", ($dryrun ? "DRYRUN" : (defined($ret) ? "success" : "ERROR")));
unless(defined($ret)) {
$send_receive_error = 1;
$ret = $err; # print the errors below
}
if(defined($ret)) {
# NOTE: if "btrfs send" fails, "btrfs receive" returns 0! so we need to parse the output...
foreach(split("\n", $ret)) {
if(/^ERROR: /) {
ERROR $';
$send_receive_error = 1;
}
elsif(/^WARNING: /) {
WARN "[btrfs send/receive] (send=$snapshot_path, receive=$target_path) $'";
}
else {
WARN "[btrfs send/receive] (send=$snapshot_path, receive=$target_path) $_" if($send_receive_error);
}
}
}
end_transaction("send-receive", ($dryrun ? "DRYRUN" : ($send_receive_error ? "ERROR" : "success")));
if($send_receive_error) {
ERROR "Failed to send/receive btrfs subvolume: $snapshot->{PRINT} " . ($parent_path ? "[$parent_path]" : "") . " -> $target->{PRINT}";
# NOTE: btrfs-progs v3.19.1 does not delete garbled received subvolume,