A collection of scripts
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 24usage() { 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 48msg() { 49 case $1 in 50 e ) printf '%b\n' "${0##*/}: $*" 1>&2 ;; 51 * ) printf '%b\n' "${0##*/}: $*" ;; 52 esac 53} 54 55while [ "$*" ] 56do 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 87done 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 96BTRSNP_DEVICE=${BTRSNP_DEVICE##*/} 97if findmnt "/mnt/$BTRSNP_DEVICE" > /dev/null 2>&1 98then btrfs_partition_path=/mnt/$BTRSNP_DEVICE 99else 100 msg e "BTRFS partition is not mounted at /mnt/$BTRSNP_DEVICE" 101 exit 1 102fi 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 106if [ -d "$btrfs_partition_path/$BTRSNP_SUBVOL" ] 107then btrfs_subvolume_path="$btrfs_partition_path/$BTRSNP_SUBVOL" 108else 109 msg e "This is not a BTRFS subvolume" 110 exit 1 111fi 112 113case $BTRSNP_READ in 114 ro ) ro="-r" ;; 115 rw ) ;; 116esac 117 118btrfs subvolume snapshot $ro "$btrfs_subvolume_path" \ 119 "${btrfs_subvolume_path}-$(date +'%F-%H_%M_%S')"