#!/bin/bash # dry run by default # >btrbk_run # with -e exectue # >btrbk_run -e # to only create the links # >btrbk_run -e -n # sudo -E bash -c 'source $BASH_SHELL_BASE/module.base; module_load btrbk; btrbk_run toot' btrbk_scripts_dir="$(dirname $(realpath "${BASH_SOURCE:-$0}"))" module_load helpers # will try to find a conf file with out without .conf extension in a few places btrbk_conf () { local file=${1:-btrbk.conf} [[ -f $file ]] && echo $file && return [[ -f $file.conf ]] && echo $file.conf && return BTRBK_CONF_DIR=${BTRBK_CONF_DIR:-/snapshots/conf} # echo $btrbk_scripts_dir # echo $BTRBK_CONF_DIR [[ -f $BTRBK_CONF_DIR/$file ]] && echo $BTRBK_CONF_DIR/$file && return [[ -f $BTRBK_CONF_DIR/$file.conf ]] && echo $BTRBK_CONF_DIR/$file.conf && return [[ -f /etc/btrbk/$file ]] && echo /etc/btrbk/$file && return [[ -f /etc/btrbk/$file.conf ]] && echo /etc/btrbk/$file.conf && return [[ -f /etc/btrbk.conf ]] && echo /etc/btrbk.conf && return return 1 } btrbk_clean () { local file=$(btrbk_conf $1) [[ ! $file ]] && return 1 sudo btrbk -c $file clean $2 } btrbk_src () { local file=$(btrbk_conf $1) [[ ! $file ]] && return 1 sudo btrbk -c $file list config --format col:h:source_subvolume } btrbk_dests () { local file=$(btrbk_conf $1) [[ ! $file ]] && return 1 local dests=$(sudo btrbk -c $file list config --format col:h:snapshot_path | tail -1) dests+=" $(sudo btrbk -c $file list target --format col:h:target_path)" echo $dests } btrbk_latest() { local file=$(btrbk_conf $1) [[ ! $file ]] && echo unable to find conf file for ${1:-btrbk.conf} && return 1 shift local latest=$(sudo btrbk -c $file list latest --format col:h:snapshot_subvolume | xargs -I % sh -c 'basename %' | sed '$!N; /^\(.*\)\n\1$/!P; D') echo $latest } btrbk_latest_snap () { local dry_run="echo" [[ $1 == "-e" ]] && dry_run="" && shift local file=$(btrbk_conf $1) [[ ! $file ]] && echo unable to find conf file for ${1:-btrbk.conf} && return 1 shift local ext=${1-sav}.$(date "+%Y%m%d") local latest=$(sudo btrbk -c $file list latest --format col:h:snapshot_subvolume | xargs -I % sh -c 'basename %' | sed '$!N; /^\(.*\)\n\1$/!P; D') [[ ( ! $latest ) || $latest == "-" ]] && echo "no latest snapshots so can't make .latest links" && return 3 local dests=$(btrbk_dests $file) if [[ $dry_run ]]; then echo dry run for latest snapshots for following destinations, NOTE: use -e to actually make them echo $dests echo "-------------------" fi echo making snapshots in each destination [[ $dry_run ]] && echo this is a dry run use -e to make snapshots for dest in $dests; do for snap in $latest; do # [[ -e $dest/${snap%%.*}.latest ]] && $dry_run_echo sudo rm $dest/${snap%%.*}.latest # TODO only do latest links for locally mounted if [[ -d $dest/$snap ]]; then local cmd="sudo btrfs subvolume snapshot $dest/$snap $dest/${snap%%.*}.${ext}" echo $cmd [[ ! $dry_run ]] && $cmd fi done done } btrbk_latest_links () { local dry_run="echo" [[ $1 == "-e" ]] && dry_run="" && shift local file=$(btrbk_conf $1) [[ ! $file ]] && echo unable to find conf file for ${1:-btrbk.conf} && return 1 shift local ext=${2:-latest} local latest=$(sudo btrbk -c $file list latest --format col:h:snapshot_subvolume | xargs -I % sh -c 'basename %' | sed '$!N; /^\(.*\)\n\1$/!P; D') [[ ( ! $latest ) || $latest == "-" ]] && echo "no latest snapshots so can't make .latest links" && return 3 local dests=$(btrbk_dests $file) if [[ $dry_run ]]; then echo dry run for making latest links for following destinations, NOTE: use -e to actually make them echo $dests echo "-------------------" fi echo making .latest symlinks in each destination for dest in $dests; do for snap in $latest; do # [[ -e $dest/${snap%%.*}.latest ]] && $dry_run_echo sudo rm $dest/${snap%%.*}.latest # TODO only do latest links for locally mounted if [[ -d $dest/$snap ]]; then local cmd="sudo ln -srfn $dest/$snap $dest/${snap%%.*}.${ext}" echo $cmd [[ ! $dry_run ]] && $cmd fi done done } btrbk_run () { local dry_run="-n" [[ $1 == "-e" ]] && dry_run="" && shift local file=$(btrbk_conf $1) [[ ! $file ]] && echo unable to find conf file for ${1:-btrbk.conf} && return 1 shift local src=$(btrbk_src $file) local snaps=$(sudo btrbk -c $file list source --format col:h:snapshot_name) local dests=$(sudo btrbk -c $file list config --format col:h:snapshot_path | tail -1) local dests+=" $(btrbk -c $file list target --format col:h:target_path)" # todo distinguish local from remote destinations and deal with differently for latest link # any pre snap tasks # for dest in $dests; do # if [[ ! -d $dest ]]; then # if confirm directory $dest does not exist, create; then # sudo mkdir -p $dest # else # echo destination $dest directory MUST exist aborting brtbk run # return 2 # fi # fi # done echo using configuration file: $file echo creating snapshots: $snaps echo from $src echo at these destinations $dests echo additional passed arguments: $@ # do snaps and backups [[ $dry_run ]] && echo backup dry run || echo Taking snapshost and making backups now... sudo btrbk -c $file run $dry_run --progress $@ # post snap/backup btrbk_latest_links $([[ $dry_run ]] || printf "%s" -e) $file } (return 0 2>/dev/null) || btrbk_run $@ btrbk_named () { # btrfs subvolume list -o . -r --sort path,gen # todo # rw vs ro -r # -f folder with extensions removed vs appended extension # figure out latest instead of depending on .latest # find unique names, then list and grep on those and use # btrfs subvolume list -o . -r --sort path+gen module_load confirm local name; local names local snapname=".latest" [[ $1 == "-s" ]] && snapname="$2" && shift 2 local src=$(realpath $1) local dest=$(realpath $2) if [[ ! -d $dest ]]; then if confirm "destination directory $dest does not exist, create it"; then sudo mkdir -p $dest else return 1 fi fi echo looking for snapshots in $src with extension matching $snapname local snaps=$(ls $src | grep "\..*$snapname" | sed 's/.\{1\}$//' | xargs -I % realpath $src/%) # while read test; do # echo $test # done <<< "$( btrfs subvolume list -o . -r --sort path+gen | get just path | get only fname)" [[ ! $snaps ]] && echo no snapshots with extension $snapname in $src && ls -la $src && return 1 echo creating snapshots for for snap in $snaps; do name=$(get_only_fname $snap) [[ $names == *"$name"* ]] && echo whoops! snapshots found for $(rm_ext $snap) using filter $snapname not unique, aborting && ls -la | grep $ && return 3 names+=" $name" echo $snap done if confirm in $dest; then local destsnap for snap in $snaps; do destsnap="$dest/$(basename $snap | cut -f 1 -d '.' )" if [[ -d $destsnap ]]; then if confirm -s snapshot $destsnap already exists do you want to over write it; then sudo btrfs subvolume delete $destsnap else return 2 fi fi sudo btrfs subvolume snapshot $@ $snap $destsnap done echo $dest ls -la $dest fi } # use snapshot to then snap latest to another location, have it edit the fstab file # #!/bin/bash # [[ $# -lt 2 ]] && echo "need to supply a and a snapshot name" && exit # # echo sed 's/$name/'$name'/g' named.conf.tmpl > $subvoldir-$name.conf # # echo sed -i 's/$subvoldir/'$subvoldir'/g' $subvoldir-$name.conf # named="$2" # src=/mnt/linuxpart # dest=/mnt/linuxpart # echo sudo mkdir -p $dest/$named # echo sudo btrfs subvolume snapshot $src/$1/@root $dest/$named/@root # echo sudo btrfs subvolume snapshot $src/$1/@opt $dest/$named/@opt # echo sudo btrfs subvolume snapshot $src/$1/@home $dest/$named/@home # echo sudo btrfs subvolume snapshot $src/@shell $dest/$named/@shell # sudo mkdir -p $dest/$named # sudo btrfs subvolume snapshot $src/$1/@root $dest/$named/@root # sudo btrfs subvolume snapshot $src/$1/@opt $dest/$named/@opt # sudo btrfs subvolume snapshot $src/$1/@home $dest/$named/@home # sudo btrfs subvolume snapshot $src/@shell $dest/$named/@shell # echo to edit: bfs_vscode $dest/$named