Skip to content

Commit 4dccf17

Browse files
committed
Refactor
- Add BORG_PASSCOMMAND - Move check_root into a function - Move mutex into a function - Add borg_get_names for later use - Add bind_mount_snapshot in order to work with borg's limitation on having to need the same absolute path for an efficient file cache - Add umounting bind mounts to the wrap_up trap function - Be more precise about gathering the mount location with awk L#124 - Switch borg_create_snap call to work with the bind_mount_paths array
1 parent 4424b9b commit 4dccf17

1 file changed

Lines changed: 64 additions & 30 deletions

File tree

snapper2borg.sh

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,27 @@ BORG_BACKUP_PATH="/mnt/external1/backups"
44
BORG_COMPRESSION="auto,zstd"
55
BORG_FLAGS="-x -s"
66
#BORG_FLAGS="-x -s --progress"
7-
BORG_PASSPHRASE="${BORG_PASSPHRASE}"
7+
#BORG_PASSPHRASE="${BORG_PASSPHRASE}"
8+
BORG_PASSCOMMAND="cat /root/.borg_password"
89
BORG_ENCRYPTION="repokey-blake2"
10+
BIND_MNT_PREFIX="/tmp/borg"
911

10-
export BORG_PASSPHRASE
12+
export BORG_PASSPHRASE BORG_PASSCOMMAND
1113
declare -A snapper_lv_snapshots snapper_mounted
1214

13-
# MUTEX Do not remove
14-
lockdir="${BORG_BACKUP_PATH}/.snapper2borg.lock"
15-
if ! mkdir "$lockdir" >/dev/null 2>&1; then
16-
echo "${0##*/} cannot run more than once, or remove the lockdir at: $lockdir"
17-
exit 1
18-
fi
19-
20-
# Check for root
21-
(( EUID == 0 )) || { echo "This script must be run as root"; exit 1; }
15+
check_root() {
16+
# Check for root
17+
(( EUID == 0 )) || { echo "This script must be run as root"; exit 1; }
18+
}
2219

23-
# Get configured snapper filesystems
24-
snapper_filesystems=($( snapper list-configs | awk 'NR > 2 { print $3 }' ))
25-
snapper_configs=($( snapper list-configs | awk 'NR>2 { print $1 }' ))
26-
snapper_devices=($(
27-
for mount in "${snapper_filesystems[@]}"; do
28-
__df_output=($( df -l --no-sync --output=source "$mount" ))
29-
echo "${__df_output[1]}"
30-
done
31-
))
20+
mutex() {
21+
# MUTEX Do not remove
22+
lockdir="${BORG_BACKUP_PATH}/.snapper2borg.lock"
23+
if ! mkdir "$lockdir" >/dev/null 2>&1; then
24+
echo "${0##*/} cannot run more than once, or remove the lockdir at: $lockdir"
25+
exit 1
26+
fi
27+
}
3228

3329
get_latest() {
3430
local config="$1"
@@ -62,21 +58,54 @@ borg_create_snap() {
6258

6359
borg_create_repo() {
6460
local config="$1"
65-
local num="$2"
66-
local mount="$3"
6761
borg init \
6862
-e "${BORG_ENCRYPTION}" \
6963
"${BORG_BACKUP_PATH}/${config}" >/dev/null 2>&1
7064
}
7165

66+
borg_get_names() {
67+
local config="$1"
68+
borg list -a "*-snapshot*" "${BORG_BACKUP_PATH}/${config}" \
69+
--format '{name}{NL}'
70+
}
71+
72+
bind_mount_snapshot() {
73+
# Returns the bind mountpoint of the snapshot
74+
local bind_path="${BIND_MNT_PREFIX}/$1"
75+
local snapshot="$2"
76+
mkdir -p "${BIND_MNT_PREFIX}" &&
77+
mount -o bind,x-mount.mkdir=0600 "$snapshot" "$bind_path"
78+
return=$?; (( return == 0 )) && echo "$bind_path"
79+
return $return
80+
}
81+
7282
wrap_up() {
7383
for config in "${!snapper_mounted[@]}"; do
7484
local num="${snapper_mounted[$config]}"
7585
mount_snapshot "$config" umount "$num"
7686
done
87+
# for mountpoint in "${bind_mount_paths[@]}"; do
88+
# umount -l "$mountpoint"
89+
# done
90+
umount -l "${bind_mount_paths[@]}"
7791
rmdir "$lockdir"
7892
}
7993

94+
trap wrap_up INT EXIT TERM
95+
96+
check_root
97+
mutex
98+
99+
# Get configured snapper filesystems
100+
snapper_filesystems=($( snapper list-configs | awk 'NR > 2 { print $3 }' ))
101+
snapper_configs=($( snapper list-configs | awk 'NR>2 { print $1 }' ))
102+
snapper_devices=($(
103+
for mount in "${snapper_filesystems[@]}"; do
104+
__df_output=($( df -l --no-sync --output=source "$mount" ))
105+
echo "${__df_output[1]}"
106+
done
107+
))
108+
80109
# Resolve LVs into a list of descendant snapshots
81110
for device in "${snapper_devices[@]}"; do
82111
# This outputs a list of snapshots into LVM2_LV_DESCENDANTS
@@ -85,22 +114,27 @@ for device in "${snapper_devices[@]}"; do
85114
eval snapper_lv_snapshots["${device##*/}"]="\$( echo \"${LVM2_LV_DESCENDANTS}\" | tr ',' '\n' )"
86115
done
87116

88-
for config in "${snapper_configs[@]}"; do
117+
for i in "${!snapper_configs[@]}"; do
118+
config="${snapper_configs[i]}"
119+
device="${snapper_devices[i]}"
89120
snapshot_num=$(get_latest "$config")
90121
if ( mount_snapshot "$config" mount "$snapshot_num" ); then
122+
snapper_mounted[$config]="$snapshot_num"
91123
snapshot_mount=$(
92-
mount | awk -v config="$config" -v num="$snapshot_num" \
93-
'$1 ~ config".*snapshot"num { print $3 }'
124+
mount | awk \
125+
-v device="$device" \
126+
-v num="$snapshot_num" \
127+
-v bind_pre="$BIND_MNT_PREFIX" \
128+
'$1 ~ device"--snapshot"num && $3 !~ bind_pre { print $3 }'
94129
)
95-
snapper_mounted[$config]="$snapshot_num"
130+
bind_mount_paths+=($( bind_mount_snapshot "${device##*/}" "$snapshot_mount" )) ||
131+
{ echo "Could not bind mount the snapshot"; exit 1; }
96132
if [[ ! -d "${BORG_BACKUP_PATH}/$config" ]]; then
97-
borg_create_repo "$config" "$snapshot_num" "$snapshot_mount" ||
133+
borg_create_repo "$config" ||
98134
{ echo "Creating the repo failed"; exit 1; }
99135
fi
100-
borg_create_snap "$config" "$snapshot_num" "$snapshot_mount"
136+
borg_create_snap "$config" "$snapshot_num" "${bind_mount_paths[-1]}"
101137
else
102138
echo "Unable to mount snapshot"; exit 1
103139
fi
104140
done
105-
106-
trap wrap_up INT EXIT TERM

0 commit comments

Comments
 (0)