]> Sergey Matveev's repositories - dotfiles.git/blobdiff - bin/bin/zsnap
Less .sh and more explicit my-
[dotfiles.git] / bin / bin / zsnap
diff --git a/bin/bin/zsnap b/bin/bin/zsnap
new file mode 100755 (executable)
index 0000000..c25a989
--- /dev/null
@@ -0,0 +1,80 @@
+#!/usr/bin/env zsh
+
+set -e
+setopt EXTENDED_GLOB
+
+usage() {
+    cat <<EOF
+Usage: $0 DATASET@SNAPPREFIX snap-initial
+       $0 DATASET@SNAPPREFIX snap
+       $0 DATASET@SNAPPREFIX sync-initial DST
+       $0 DATASET@SNAPPREFIX sync DST
+       $0 DATASET@SNAPPREFIX clean COUNT
+EOF
+    exit 1
+}
+
+enccmd=(gpg --compress-level 0 --encrypt --recipient offline)
+
+[[ $# -ge 2 ]] || usage
+
+what=$1
+action=$2
+
+zmodload -F zsh/datetime b:strftime
+now=$(strftime %Y%m%d%H%M)
+[[ $what =~ / ]] && depth=1 || depth=${#${(s./.)what}}
+snaps=$(zfs list -t snap -d $depth -o name -H | grep $what | sort -nr)
+snaps=(${(f)snaps})
+latest=${snaps[1]}
+latest_filename=${latest:gs#/#%}
+
+case $action in
+    snap-initial)
+        zfs snap -r $what-$now
+        print $what-$now
+        ;;
+    snap)
+        [[ -n $latest ]]
+        [[ "$what-$now" != $latest ]]
+        zfs snap -r $what-$now
+        print $what-$now
+        ;;
+    sync-initial)
+        dst=$3
+        [[ -d $dst ]] || usage
+        setopt PIPE_FAIL
+        zfs send -Rv $latest | zstd | $enccmd > $dst/$latest_filename.zfs.zst.gpg
+        sync
+        touch $dst/$latest_filename.from
+        ;;
+    sync)
+        dst=$3
+        [[ -d $dst ]] || usage
+        latest_dst=($dst/*~$dst/.*(.L0Onn[1]))
+        [[ $latest_dst ]]
+        latest_dst=${latest_dst[1]}
+        latest_dst=${${latest_dst##*/}%.from}
+        [[ $latest_dst != $latest_filename ]]
+        setopt PIPE_FAIL
+        set -x
+        zfs send -Rv -i ${latest_dst:gs#%#/} $latest | zstd | $enccmd > \
+            $dst/$latest_filename.zfs.zst.gpg
+        set +x
+        sync
+        print $latest_dst > $dst/$latest_filename.from
+        ;;
+    clean)
+        count=$3
+        [[ -n $count ]] || usage
+        count=$(( $count + 1 ))
+        for snap in $snaps ; do
+            count=$(( $count - 1 ))
+            [[ $count -le 0 ]] || continue
+            zfs destroy -Rv $snap
+        done
+        ;;
+    *)
+        usage
+        ;;
+esac