-
Notifications
You must be signed in to change notification settings - Fork 39
/
bsnap.sh
executable file
·82 lines (63 loc) · 2.47 KB
/
bsnap.sh
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
#! /usr/bin/bash
# exit on first error
set -e
backupdir="$HOME/_backup_snapshots"
usage() {
echo $@ >&2
echo "Usage: $0 {snapshot|transfer} ...
snapshot Create snapshots for every subvolume configured in '\$backupdir/*'.
The subvolume is specified by a symlink '\$backupdir/*/cur'
pointing to a Btrfs subvolume.
transfer <dst> Transfer all snapshots from '\$backupdir/*/' to '<dst>/', which
should be other Btrfs partition. The tree structure is kept
intact.
\$backupdir is set to '$backupdir'
" >&2
}
transfer() {
src="$1" # e.g. ~/_backup_snapshots/Bbox/
dst="$2" # e.g. /media/WD1T/backup-lahwaacz/Bbox/
[[ ! -d "$dst" ]] && mkdir "$dst"
# get list of snapshots to transfer
src_snapshots=($(find "$src" -mindepth 1 -maxdepth 1 -type d | sort))
_len=${#src_snapshots[@]}
for ((i=0; i<$_len; i++)); do
if [[ -e "$dst/$(basename ${src_snapshots[$i]})" ]]; then
# nothing to transfer
echo "Snapshot '$dst/$(basename ${src_snapshots[$i]})' already exists"
continue
fi
# There is currently an issue that the snapshots to be used with "btrfs send"
# must be physically on the disk, or you may receive a "stale NFS file handle"
# error. This is accomplished by "sync" after the snapshot
#
# ref: http://marc.merlins.org/perso/btrfs/post_2014-03-22_Btrfs-Tips_-Doing-Fast-Incremental-Backups-With-Btrfs-Send-and-Receive.html
sync
dst_snapshots=($(find "$dst" -mindepth 1 -maxdepth 1 -type d | sort))
if [[ $i -eq 0 ]]; then
# no parent, make initial transfer
sudo sh -c "btrfs send ${src_snapshots[$i]} | btrfs receive $dst"
else
sudo sh -c "btrfs send -p ${src_snapshots[(($i-1))]} ${src_snapshots[$i]} | btrfs receive $dst"
fi
done
}
case $1 in
snapshot)
for dir in "$backupdir"/*; do
if [[ -L "$dir/cur" ]]; then
btrfs subvolume snapshot -r $(realpath "$dir/cur") "$dir/$(date +%F-%T)"
else
echo "$dir/cur does not exist or is not a symlink"
fi
done
;;
transfer)
[ -n "$2" -a -d "$2" ] || usage "Invalid destination path"
for dir in "$backupdir"/*; do
transfer "$dir" "$2"/$(basename "$dir")
done
;;
*)
usage "Incorrect invocation"
esac