mirror of https://github.com/digint/btrbk
btrbk: catch exact error from "btrfs subvolume show"; instruct user to fix ssh_filter_btrbk.sh if it rejected the ssh command
parent
bea010dce0
commit
c23674fca8
|
@ -1,3 +1,11 @@
|
||||||
|
btrbk-current
|
||||||
|
|
||||||
|
* IMPORTANT: please update ssh_filter_btrbk.sh on all remote hosts!
|
||||||
|
* Set PATH variable instead of using absolute "/sbin/btrfs" for
|
||||||
|
compatibility with all linux distros out there, which all install
|
||||||
|
'btrfs' in different locations (closes: #20).
|
||||||
|
* Catch and display errors from "btrfs subvolume show".
|
||||||
|
|
||||||
btrbk-0.17.1
|
btrbk-0.17.1
|
||||||
|
|
||||||
* Bugfix: send/receive: delete possibly left-behind garbled
|
* Bugfix: send/receive: delete possibly left-behind garbled
|
||||||
|
|
29
btrbk
29
btrbk
|
@ -88,6 +88,7 @@ my %uuid_fs_map; # map UUID to URL
|
||||||
|
|
||||||
my $dryrun;
|
my $dryrun;
|
||||||
my $loglevel = 1;
|
my $loglevel = 1;
|
||||||
|
my $err = "";
|
||||||
|
|
||||||
my $ip_addr_match = qr/(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/;
|
my $ip_addr_match = qr/(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/;
|
||||||
my $host_name_match = qr/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])/;
|
my $host_name_match = qr/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])/;
|
||||||
|
@ -146,6 +147,7 @@ sub run_cmd($;$)
|
||||||
my $ret = "";
|
my $ret = "";
|
||||||
$cmd =~ s/^\s+//;
|
$cmd =~ s/^\s+//;
|
||||||
$cmd =~ s/\s+$//;
|
$cmd =~ s/\s+$//;
|
||||||
|
$err = "";
|
||||||
if($non_destructive || (not $dryrun)) {
|
if($non_destructive || (not $dryrun)) {
|
||||||
DEBUG "### $cmd";
|
DEBUG "### $cmd";
|
||||||
$ret = `$cmd`;
|
$ret = `$cmd`;
|
||||||
|
@ -155,6 +157,19 @@ sub run_cmd($;$)
|
||||||
my $exitcode= $? >> 8;
|
my $exitcode= $? >> 8;
|
||||||
my $signal = $? & 127;
|
my $signal = $? & 127;
|
||||||
DEBUG "Command execution failed (exitcode=$exitcode" . ($signal ? ", signal=$signal" : "") . "): \"$cmd\"";
|
DEBUG "Command execution failed (exitcode=$exitcode" . ($signal ? ", signal=$signal" : "") . "): \"$cmd\"";
|
||||||
|
|
||||||
|
if($ret =~ /ssh command rejected/) {
|
||||||
|
# catch errors from ssh_filter_btrbk.sh
|
||||||
|
$err = "ssh command rejected (please fix ssh_filter_btrbk.sh)";
|
||||||
|
}
|
||||||
|
elsif($ret =~ /^ERROR: (.*)/) {
|
||||||
|
# catch errors from btrfs command
|
||||||
|
$err = $1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG "Unparseable error: $ret";
|
||||||
|
$err = "unparseable error";
|
||||||
|
}
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -580,7 +595,7 @@ sub btrfs_subvolume_detail($)
|
||||||
my $vol = shift || die;
|
my $vol = shift || die;
|
||||||
my $path = $vol->{PATH} // die;
|
my $path = $vol->{PATH} // die;
|
||||||
my $rsh = $vol->{RSH} || "";
|
my $rsh = $vol->{RSH} || "";
|
||||||
my $ret = run_cmd("$rsh btrfs subvolume show '$path' 2>/dev/null", 1);
|
my $ret = run_cmd("$rsh btrfs subvolume show '$path' 2>&1", 1);
|
||||||
return undef unless(defined($ret));
|
return undef unless(defined($ret));
|
||||||
|
|
||||||
my $real_path;
|
my $real_path;
|
||||||
|
@ -1352,12 +1367,12 @@ MAIN:
|
||||||
# FIXME: allow ssh:// src/dest (does not work since the configuration is not yet read).
|
# FIXME: allow ssh:// src/dest (does not work since the configuration is not yet read).
|
||||||
|
|
||||||
my $src_vol = vinfo($src_url, { CONTEXT => "cmdline" });
|
my $src_vol = vinfo($src_url, { CONTEXT => "cmdline" });
|
||||||
unless(vinfo_root($src_vol)) { ERROR "Failed to fetch subvolume detail for: $src_vol->{PRINT}"; exit 1; }
|
unless(vinfo_root($src_vol)) { ERROR "Failed to fetch subvolume detail for: $src_vol->{PRINT}" . ($err ? ": $err" : ""); exit 1; }
|
||||||
if($src_vol->{is_root}) { ERROR "Subvolume at \"$src_url\" is btrfs root!"; exit 1; }
|
if($src_vol->{is_root}) { ERROR "Subvolume at \"$src_url\" is btrfs root!"; exit 1; }
|
||||||
unless($src_vol->{cgen}) { ERROR "Subvolume at \"$src_url\" does not provide cgen"; exit 1; }
|
unless($src_vol->{cgen}) { ERROR "Subvolume at \"$src_url\" does not provide cgen"; exit 1; }
|
||||||
|
|
||||||
my $target_vol = vinfo($target_url, { CONTEXT => "cmdline" });
|
my $target_vol = vinfo($target_url, { CONTEXT => "cmdline" });
|
||||||
unless(vinfo_root($target_vol)) { ERROR "Failed to fetch subvolume detail for: $src_vol->{PRINT}"; exit 1; }
|
unless(vinfo_root($target_vol)) { ERROR "Failed to fetch subvolume detail for: $src_vol->{PRINT}" . ($err ? ": $err" : ""); exit 1; }
|
||||||
unless($src_vol->{cgen}) { ERROR "Subvolume at \"$src_url\" does not provide cgen"; exit 1; }
|
unless($src_vol->{cgen}) { ERROR "Subvolume at \"$src_url\" does not provide cgen"; exit 1; }
|
||||||
|
|
||||||
my $uuid_list = vinfo_fs_list($src_vol);
|
my $uuid_list = vinfo_fs_list($src_vol);
|
||||||
|
@ -1541,7 +1556,7 @@ MAIN:
|
||||||
next if($config_vol->{ABORTED});
|
next if($config_vol->{ABORTED});
|
||||||
my $sroot = vinfo($config_vol->{url}, $config_vol);
|
my $sroot = vinfo($config_vol->{url}, $config_vol);
|
||||||
unless(vinfo_root($sroot)) {
|
unless(vinfo_root($sroot)) {
|
||||||
$config_vol->{ABORTED} = "Failed to fetch subvolume detail";
|
$config_vol->{ABORTED} = "Failed to fetch subvolume detail" . ($err ? ": $err" : "");
|
||||||
WARN "Skipping volume \"$sroot->{PRINT}\": $config_vol->{ABORTED}";
|
WARN "Skipping volume \"$sroot->{PRINT}\": $config_vol->{ABORTED}";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
@ -1559,7 +1574,7 @@ MAIN:
|
||||||
$svol = vinfo_child($sroot, $config_subvol->{rel_path});
|
$svol = vinfo_child($sroot, $config_subvol->{rel_path});
|
||||||
my $detail = btrfs_subvolume_detail($svol);
|
my $detail = btrfs_subvolume_detail($svol);
|
||||||
unless($detail) {
|
unless($detail) {
|
||||||
$config_subvol->{ABORTED} = "Failed to fetch subvolume detail";
|
$config_subvol->{ABORTED} = "Failed to fetch subvolume detail" . ($err ? ": $err" : "");
|
||||||
WARN "Skipping subvolume \"$svol->{PRINT}\": $config_subvol->{ABORTED}";
|
WARN "Skipping subvolume \"$svol->{PRINT}\": $config_subvol->{ABORTED}";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
@ -1596,7 +1611,7 @@ MAIN:
|
||||||
{
|
{
|
||||||
my $droot = vinfo($config_target->{url}, $config_target);
|
my $droot = vinfo($config_target->{url}, $config_target);
|
||||||
unless(vinfo_root($droot)) {
|
unless(vinfo_root($droot)) {
|
||||||
$config_target->{ABORTED} = "Failed to fetch subvolume detail";
|
$config_target->{ABORTED} = "Failed to fetch subvolume detail" . ($err ? ": $err" : "");
|
||||||
WARN "Skipping target \"$droot->{PRINT}\": $config_target->{ABORTED}";
|
WARN "Skipping target \"$droot->{PRINT}\": $config_target->{ABORTED}";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
@ -1629,7 +1644,7 @@ MAIN:
|
||||||
DEBUG "Subvolume not parsed yet, fetching info: $url";
|
DEBUG "Subvolume not parsed yet, fetching info: $url";
|
||||||
$vol = vinfo($url, { CONTEXT => "cmdline" });
|
$vol = vinfo($url, { CONTEXT => "cmdline" });
|
||||||
unless(vinfo_root($vol)) {
|
unless(vinfo_root($vol)) {
|
||||||
ERROR "Failed to fetch subvolume detail for: $url";
|
ERROR "Failed to fetch subvolume detail for: $url" . ($err ? ": $err" : "");
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ reject_and_die()
|
||||||
if [ -n "$enable_log" ]; then
|
if [ -n "$enable_log" ]; then
|
||||||
/usr/bin/logger -p auth.err -t ssh_filter_btrbk.sh "$LOGNAME $SSH_CLIENT REJECT: $SSH_ORIGINAL_COMMAND"
|
/usr/bin/logger -p auth.err -t ssh_filter_btrbk.sh "$LOGNAME $SSH_CLIENT REJECT: $SSH_ORIGINAL_COMMAND"
|
||||||
fi
|
fi
|
||||||
/bin/echo "ssh command rejected" 1>&2;
|
/bin/echo "ERROR: ssh command rejected" 1>&2;
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue