dsnap-sync: rework BTRFS_PIPE handling

* redirect any output of btrfs send/receive to a PIPE
* on failure, output saved messages to this PIPE
* cleanup PIPE on program termination

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
This commit is contained in:
2018-09-28 14:34:48 +02:00
parent 6dcd0f7b45
commit 3f00ef6702

104
bin/dsnap-sync Normal file → Executable file
View File

@@ -36,21 +36,21 @@ SNAPPER_CONFIG=/etc/default/snapper
SNAPPER_TEMPLATE_DIR=/etc/snapper/config-templates
SNAPPER_CONFIG_DIR=/etc/snapper/configs
# define fifo pipes
TMPDIR_PIPE=$(mktemp --tmpdir=$XDG_RUNTIME_DIR/$progname -d)
PIPE=$TMPDIR_PIPE/$progname.out
# Create TEMPDIR
test ! -d $XDG_RUNTIME_DIR/$progname && mkdir -p $XDG_RUNTIME_DIR/$progname
mkfifo $PIPE
systemd-cat --identifier="$progname" < $PIPE &
TMPDIR=$(mktemp --tmpdir=$XDG_RUNTIME_DIR/$progname -d)
BTRFS_PIPE=$TMPDIR_PIPE/btrfs.out
BTRFS_SEND_PIPE=$TMPDIR_PIPE/btrfs_send.out
BTRFS_RECIEVE_PIPE=$TMPDIR_PIPE/btrfs_recieve.out
#mkfifo $BTRFS_PIPE
#systemd-cat --identifier="btrfs-pipe" < $BTRFS_PIPE &
# define fifo pipes
#PIPE=$TMPDIR/$progname.out
#mkfifo $PIPE
#systemd-cat --identifier="$progname" < $PIPE &
BTRFS_PIPE=$TMPDIR/btrfs.fifo
test -p $BTRFS_PIPE && mkfifo $BTRFS_PIPE
# redirect descriptors to given pipes
exec 3>$PIPE 4>$BTRFS_PIPE
#exec 3>$PIPE
4>$BTRFS_PIPE
# global variables
args=
@@ -1447,6 +1447,7 @@ run_backup () {
if [ $donotify -gt 0 ]; then
notify_info "Backup in progress" "NOTE: Skipping '$selected_config' configuration."
fi
# go for next configuration
i=$(($i+1))
continue
fi
@@ -1497,10 +1498,14 @@ run_backup () {
verify_snapper_structure "backup_root=$backup_root" "snapper_target_config=$snapper_target_config" "snapper_target_id=$snapper_target_id" "remote=$remote"
;;
btrfs-archive)
# check for last common snapshot
snapper_source_id=$snapper_source_sync_id
snapper_source_snapshot=$SUBVOLUME/.snapshots/$snapper_source_sync_id/$snapper_snapshot_name
snapper_source_info=$SUBVOLUME/.snapshots/$snapper_source_sync_id/info.xml
if [ $snapper_source_sync_id -eq 0 ]; then
create_snapshot
else
# check for last common snapshot
snapper_source_id=$snapper_source_sync_id
snapper_source_snapshot=$SUBVOLUME/.snapshots/$snapper_source_sync_id/$snapper_snapshot_name
snapper_source_info=$SUBVOLUME/.snapshots/$snapper_source_sync_id/info.xml
fi
# targets backup location will save the snapshots in the subdirectory (snapshot-id)
# the snapshot is either the base snapshot (flat-file), or an incremental snapshot (btrfs-send stream)
@@ -1541,7 +1546,6 @@ run_backup () {
#fi
# need to substitue btrfs 'x.yyGiB' suffix, since pv will need 'xG'
#if [ $snapper_source_snapshot_size -ge 1073741824 ]; then
if [ $snapper_source_snapshot_size -ge 1048576 ]; then
snapper_source_snapshot_size=$(btrfs qgroup show -f --gbytes $snapper_source_snapshot 2>/dev/null \
| awk 'FNR>2 { gsub(/.[0-9][0-9]GiB/,"G"); print $2}')
@@ -1592,28 +1596,29 @@ run_backup () {
case $selected_fstype in
btrfs)
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>$BTRFS_SEND_PIPE \
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>4 \
| $cmd_pv \
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 2>$BTRFS_RECIEVE_PIPE"
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 1>4 2>&1"
;;
*)
# Can't use btrfs receive, since target filesystem can't support btrfs snapshot feature
snapper_target_stream=${snapper_target_id}_${archive_type}.btrfs
if [ ! -f $snapper_target_snapshot/$snapper_target_stream ]; then
if [ -z $remote ]; then
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>$BTRFS_SEND_PIPE \
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>/dev/null \
| $cmd_pv \
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream 2>$BTRFS_RECIEVE_PIPE"
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream"
else
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>$BTRFS_SEND_PIPE \
cmd="btrfs send $btrfs_verbose_flag $snapper_source_snapshot 2>/dev/null \
| $cmd_pv \
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>$BTRFS_RECIEVE_PIPE"
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>4"
fi
else
if [ $verbose -ge 2 ]; then
printf "${RED}BTRFS_Stream: %s${NO_COLOR} already saved.\n" \
"$snapper_target_snapshot/$snapper_target_stream"
fi
# go for next configuration
i=$(($i+1))
continue
fi
@@ -1631,11 +1636,13 @@ run_backup () {
if [ $verbose -ge 3 ]; then
printf "cmd: '%s'\n" "$cmd"
fi
$(eval $cmd) 1>/dev/null
$(eval $cmd)
if [ "$?" -gt 0 ]; then
printf "${RED}BTRFS_SEND_PIPE: %s${NO_COLOR}\n" "$(cat $BTRFS_SEND_PIPE)"
printf "${RED}BTRFS_RECIEVE_PIPE: %s${NO_COLOR}\n" "$(cat $BTRFS_RECIEVE_PIPE)"
die "btrfs pipe error."
printf "${RED}BTRFS_PIPE: %s${NO_COLOR}\n" "$(cat <4)"
# go for next configuration
i=$(($i+1))
continue
#die "btrfs pipe error."
fi
else
# source holds synced snapshots
@@ -1707,21 +1714,21 @@ run_backup () {
# subvolume on the source and the receiving location (the parent-id).
# using "btrfs send -p" instead of "btrfs send -c", then no parent search would be
# needed (Andreij explained in: https://www.spinics.net/lists/linux-btrfs/msg69369.html)
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_PIPE \
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>4 \
| $cmd_pv \
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 2>$BTRFS_PIPE"
$cmd_ionice $ssh btrfs receive $btrfs_verbose_flag $snapper_target_snapshot/ 1>4 2>&1"
;;
*)
# Can't use btrfs receive, since target filesystem can't support btrfs snapshot feature
snapper_target_stream=${snapper_target_id}_incremental.btrfs
if [ -z $remote ]; then
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_SEND_PIPE \
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>4 \
| $cmd_pv \
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream 2>$BTRFS_PIPE"
$cmd_ionice cat > $snapper_target_snapshot/$snapper_target_stream 2>4"
else
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>$BTRFS_SEND_PIPE \
cmd="btrfs send $btrfs_verbose_flag -p $snapper_common_sync_snapshot $snapper_source_snapshot 2>4 \
| $cmd_pv \
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>$BTRFS_PIPE"
$cmd_ionice $ssh 'cat > $snapper_target_snapshot/$snapper_target_stream' 2>4"
fi
;;
esac
@@ -1734,21 +1741,19 @@ run_backup () {
if [ $verbose -ge 3 ]; then
printf "${GREEN}btrfs command:${NO_COLOR} '%s'\n" "$cmd"
fi
$(eval $cmd) 2>&1 1>/dev/null
case $? in
$(eval $cmd)
ret=$?
case $ret in
0)
;;
127)
printf "${MAGENTA}btrfs pipe return-code: ${GREEN}'127'${NO_COLOR}\n"
;;
*)
printf "${RED}btfs pipe ERROR!\n"
printf "${RED}BTRFS_PIPE: %s${NO_COLOR}\n" "$(cat $BTRFS_PIPE)"
#printf "${RED}BTRFS_SEND_PIPE: %s${NO_COLOR}\n" "$(cat $BTRFS_SEND_PIPE)"
#printf "${RED}BTRFS_RECIEVE_PIPE: %s${NO_COLOR}\n" "$(cat $BTRFS_RECIEVE_PIPE)"
#die "btrfs pipe error."
# go for next configuration
printf "${RED}btfs pipe ERROR: '%s'!\n" "$ret"
printf "${RED}BTRFS_PIPE: %s${NO_COLOR}\n" "$(cat <4)"
run_cleanup ${selected_config}
# go for next configuration
i=$(($i+1))
continue
;;
@@ -1863,7 +1868,6 @@ run_finalize () {
snapper_source_info=$(eval echo \$snapper_source_info_$i)
snapper_target_config=$(eval echo \$snapper_target_config_$i)
snapper_target_snapshot=$(eval echo \$snapper_target_snapshot_$i)
#tape_id=$(eval echo \$tape_id_$i)
# It's important not to change the values of the snapper key/value pairs ($userdata)
# which is stored in snappers info.xml file of the source snapshot.
@@ -1894,7 +1898,7 @@ run_finalize () {
local ii_sleep=15
# Solution2: kill running snapperd
# -> will restart and sync; any unseen interdependencies
# -> will restart and sync any unseen dependencies
snapperd_pid=$(eval $ssh pgrep snapperd)
if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Kill runnint ${GREEN}snapperd${MAGENTA} on target id:${GREEN}'%s'${NO_COLOR} ...\n" \
@@ -2008,7 +2012,6 @@ run_finalize () {
if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Tagging snapper metadata${NO_COLOR} for snapper id ${GREEN}'%s'${NO_COLOR} on source for configuration ${GREEN}'%s'${NO_COLOR} ...\n" \
"$snapper_source_id" "$selected_config"
#printf "calling: '%s'\n" "$(eval $cmd)"
printf "calling: '%s'\n" "$cmd"
fi
ret=$(eval "$cmd")
@@ -2018,7 +2021,7 @@ run_finalize () {
sync
fi
if [ ${#snapper_source_sync_id} -gt 0 ]; then
# TODO: no method to remove userdata pair, use awk
# TODO: no snapper method to remove userdata pair, use awk
cmd="snapper --config $selected_config modify \
--description \"$snap_description_finished\" \
--userdata \"important=no\" \
@@ -2952,15 +2955,16 @@ run_config_preparation
run_backup
# cleanup
#if [ -f $PIPE ]; then
# rm -f $PIPE || die "Failed to cleanup temporary pipe '%s'\n" "$PIPE"
#fi
if [ -d $TMPDIR_PIPE ]; then
rm -rf $TMPDIR_PIPE || die "Failed to cleanup temporary directory '%s'\n" "$TMPDIR_PIPE"
if [ -d $TMPDIR ]; then
rm -rf $TMPDIR || die "Failed to cleanup temporary directory '%s'\n" "$TMPDIR"
#printf "${RED}TODO: ${NO_COLOR}Will remove $TMPDIR}"
fi
printf "${BLUE}Backups done!${NO_COLOR}\n"
exec 3>&-
# close the read file descriptor
#exec 3>&-
exec 4>&-
if [ $donotify -gt 0 ]; then
if [ "$uuid_cmdline" != "none" ]; then