-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbtrfs-subvolume-multisend.sh
More file actions
executable file
·108 lines (92 loc) · 2.54 KB
/
Copy pathbtrfs-subvolume-multisend.sh
File metadata and controls
executable file
·108 lines (92 loc) · 2.54 KB
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
#!/bin/bash
# A simple script to transfer btrfs snapshots from one subvolume to another,
# by martinb@marbu.eu, Apache License 2.0, 2026
SCRIPTNAME=$(basename "$0")
SNAPSHOTS=()
show_help()
{
echo "For given btrfs subvolume mounted at ORIGIN_PATH with many snapshot"
echo "subvolumes inside, copy subvolumes starting FIRST_VOL_NAME until the"
echo "lastest one to another btrfs filesystem subvolume at TARGET_PATH using"
echo "btrfs send/receive feature."
echo
echo "Usage: ${SCRIPTNAME} [-d] ORIGIN_PATH FIRST_VOL_NAME TARGET_PATH"
echo
echo " -d dry/debug mode (don't perform any actions, just print commands)"
echo " -x use 'set -x' to indicate what is happening"
echo " -h show help (this message)"
}
get_snapshots()
{
ORIGIN_D=$1
SN_FIRST=$2
FOUND=0
ORIGIN_NAME=$(basename "$ORIGIN_D")
while IFS= read -r LINE; do
if [[ ${FOUND} -eq 0 ]]; then
if [[ "${LINE}" =~ ${ORIGIN_NAME}\/${SN_FIRST}$ ]]; then
SNAPSHOTS+=("${SN_FIRST}")
FOUND=1
else
continue
fi
else
SNAP_PATH=$(cut -d$'\t' -f 7 <<< "${LINE}")
SNAP_NAME=$(basename "${SNAP_PATH}")
SNAPSHOTS+=("${SNAP_NAME}")
fi
done < <(btrfs subvolume list -o "${ORIGIN_D}" -s -t | tail -n +3)
}
#
# main
#
if [[ $# = 0 ]]; then
show_help
exit
fi
unset DEBUG
unset TRACE
while getopts "dxh" OPT; do
case $OPT in
d) DEBUG=echo;;
x) TRACE=1;;
h) show_help;
exit;;
*) echo;
show_help;
exit 1;;
esac
done
shift $((OPTIND-1))
ORIGIN_D=$1
SN_FIRST=$2
TARGET_D=$3
get_snapshots "${ORIGIN_D}" "${SN_FIRST}"
SNAP_LEN=${#SNAPSHOTS[@]}
if [[ ! -d "${ORIGIN_D}/${SN_FIRST}" ]]; then
echo "error: first source snapshot doesn't exist" >&2
exit 1
fi
if [[ ${TRACE} ]]; then
set -x
fi
# send the first snapshots if it's not already present in the target volume
if [[ ! -d "${TARGET_D}/${SN_FIRST}" ]]; then
if [[ ${DEBUG} ]]; then
echo btrfs send "${ORIGIN_D}/${SN_FIRST}" \| btrfs receive "${TARGET_D}"
else
btrfs send "${ORIGIN_D}/${SN_FIRST}" | btrfs receive "${TARGET_D}"
if [[ $? -ne 0 ]]; then
echo "error: transfer of the first snapshot failed" >&2
exit 1
fi
fi
fi
# send the remaining snapshots as incremental stream, referencing parent
for i in $(seq 1 $((SNAP_LEN - 1))); do
if [[ ${DEBUG} ]]; then
echo btrfs send -p "${ORIGIN_D}/${SNAPSHOTS[(($i-1))]}" "${ORIGIN_D}/${SNAPSHOTS[$i]}" \| btrfs receive "${TARGET_D}"
else
btrfs send -p "${ORIGIN_D}/${SNAPSHOTS[(($i-1))]}" "${ORIGIN_D}/${SNAPSHOTS[$i]}" | btrfs receive "${TARGET_D}"
fi
done