-119
scritps/btrsnp
-119
scritps/btrsnp
···
1
-
#!/bin/sh
2
-
# Create a BTRFS snapshot of a subvolume
3
-
4
-
# This script is possibly highly specific to my current BTRFS setup and may not
5
-
# work the way you want it to for your system
6
-
7
-
# My current (2021-09-27) BTRFS is as follows:
8
-
# BTRFS Partition (mounted to /mnt/nvme0n1p2 for easy access to subvolumes)
9
-
# - gentoo (mounted either to / or /mnt/gentoo)
10
-
# - home (mounted to /home)
11
-
# - sys-misc (mounted to /mnt/sys-misc)
12
-
# - void (mounted either to / or /mnt/void)
13
-
14
-
# Snapshots will be saved with the name `SUBVOLUMENAME-$(date +%F-%H_$M_%S)`
15
-
16
-
[ "$BTRSNP_DEVICE" ] || BTRSNP_DEVICE=$(findmnt -nvo SOURCE /)
17
-
[ "$BTRSNP_READ" ] || BTRSNP_READ=ro
18
-
[ "$BTRSNP_SUBVOL" ] || {
19
-
BTRSNP_SUBVOL=$(findmnt -no SOURCE /)
20
-
BTRSNP_SUBVOL=${BTRSNP_SUBVOL##*/}
21
-
BTRSNP_SUBVOL=${BTRSNP_SUBVOL%]}
22
-
}
23
-
24
-
usage() {
25
-
while read -r line
26
-
do printf '%b\n' "$line"
27
-
done <<-USAGE
28
-
usage: ${0##*/} [OPTIONS]
29
-
30
-
options:
31
-
\t-d DEVICE - select which partition the subvolume is on
32
-
\t-h - displays this message
33
-
\t-r [ro|rw] - determine if the snapshot should be readonly
34
-
\t-s SUBVOL - select which subvolume to snapshot
35
-
36
-
environment variables:
37
-
\tBTRSNP_DEVICE - selects which partition the subvolume is on
38
-
\t defaults to the root partition
39
-
\tBTRSNP_READ - determine if the snapshot should be readonly
40
-
\t defaults to \`ro\`
41
-
\tBTRSNP_SUBVOL - selects which subvolume to snapshot
42
-
\t defaults to the subvolume mounted at as /
43
-
USAGE
44
-
45
-
exit "${1:-1}"
46
-
}
47
-
48
-
msg() {
49
-
case $1 in
50
-
e ) printf '%b\n' "${0##*/}: $*" 1>&2 ;;
51
-
* ) printf '%b\n' "${0##*/}: $*" ;;
52
-
esac
53
-
}
54
-
55
-
while [ "$*" ]
56
-
do
57
-
case $1 in
58
-
- ) shift; continue ;;
59
-
-- ) shift; break ;;
60
-
-* ) flag=${1#-}; shift ;;
61
-
* ) shift; continue ;;
62
-
esac
63
-
64
-
while [ "$flag" ]
65
-
do
66
-
arg=${flag%"${flag#?}"}
67
-
68
-
case $arg in
69
-
d ) BTRSNP_DEVICE="$1"; shift ;;
70
-
h ) usage 0 ;;
71
-
s ) BTRSNP_SUBVOL="$1"; shift ;;
72
-
r )
73
-
[ "$1" ] || BTRSNP_READ="rw" && {
74
-
case $1 in
75
-
ro ) BTRSNP_READ="ro" ;;
76
-
rw ) BTRSNP_READ="rw" ;;
77
-
* ) msg e "$1: invalid option argument for -$arg"; usage 1 ;;
78
-
esac
79
-
shift
80
-
}
81
-
;;
82
-
* ) msg e "-$arg: invalid argument"; usage 1 ;;
83
-
esac
84
-
85
-
flag=${flag#?}
86
-
done
87
-
done
88
-
89
-
# shellcheck disable=SC2015
90
-
[ "$BTRSNP_DEVICE" ] && [ "$BTRSNP_SUBVOL" ] || {
91
-
msg e "a device and subvolume are required"
92
-
usage 1
93
-
}
94
-
95
-
# Look for the raw BTRFS mount in /mnt this may be changeable in the future
96
-
BTRSNP_DEVICE=${BTRSNP_DEVICE##*/}
97
-
if findmnt "/mnt/$BTRSNP_DEVICE" > /dev/null 2>&1
98
-
then btrfs_partition_path=/mnt/$BTRSNP_DEVICE
99
-
else
100
-
msg e "BTRFS partition is not mounted at /mnt/$BTRSNP_DEVICE"
101
-
exit 1
102
-
fi
103
-
104
-
# If I find a more accurate way to check if a directory is a subvolume I will implement it, but for
105
-
# now, just check if it's a directory
106
-
if [ -d "$btrfs_partition_path/$BTRSNP_SUBVOL" ]
107
-
then btrfs_subvolume_path="$btrfs_partition_path/$BTRSNP_SUBVOL"
108
-
else
109
-
msg e "This is not a BTRFS subvolume"
110
-
exit 1
111
-
fi
112
-
113
-
case $BTRSNP_READ in
114
-
ro ) ro="-r" ;;
115
-
rw ) ;;
116
-
esac
117
-
118
-
btrfs subvolume snapshot $ro "$btrfs_subvolume_path" \
119
-
"${btrfs_subvolume_path}-$(date +'%F-%H_%M_%S')"