diff options
| author | Benjamin Linskey | 2025-08-13 16:48:58 -0400 |
|---|---|---|
| committer | Benjamin Linskey | 2025-08-13 16:48:58 -0400 |
| commit | 52da4bda88d915adba69af03557e5d49b0fd6e1b (patch) | |
| tree | f451ad3c5969d613eef1ccf4078a5b8f43703562 | |
| parent | f5970ac2d29374e02139aa837566d50a4e3f1efa (diff) | |
| download | zfs-snapshots-52da4bda88d915adba69af03557e5d49b0fd6e1b.tar.gz | |
Refactor script
| -rwxr-xr-x | snapshots.sh | 159 |
1 files changed, 86 insertions, 73 deletions
diff --git a/snapshots.sh b/snapshots.sh index d432526..8bdb161 100755 --- a/snapshots.sh +++ b/snapshots.sh @@ -65,10 +65,77 @@ usage() { printf "usage: %s [-cplrnvh] [-t tag] [-k num] [dataset ...]\n" "$0" } +check_args() { + if [ -z "$create" ] && [ -z "$prune" ] && [ -z "$list" ]; then + printf "At least one of -c, -p, and -l must be specified.\n" + usage + exit 1 + fi + + if [ "$#" -eq 0 ] && { [ -n "$create" ] || [ -n "$prune" ]; }; then + printf "At least one dataset must be specified\n" + usage + exit 1 + fi + + if { [ -n "$create" ] || [ -n "$prune" ]; } && [ -z "$tag" ]; then + printf "Missing -t option\n" + usage + exit 1 + fi + + if [ -n "$prune" ] && [ -z "$keep" ]; then + printf "Missing -k option\n" + usage + exit 1 + fi + + if [ -z "$prune" ] && [ -n "$keep" ]; then + printf "\-k option is only valid with -p\n" + usage + exit 1 + fi +} + +create_snapshots() { + create_cmd='zfs snapshot' + if [ -n "$recursive" ]; then + create_cmd="$create_cmd -r" + fi + readonly create_cmd + + for dataset in "$@"; do + # FreeBSD's date -I option uses a "+00:00" suffix rather than "Z", and + # the + character is illegal in snapshot names, so we have to specify + # the format manually. + cmd="$create_cmd ${dataset}@${tag}-$(date -z utc +%Y-%m-%dT%H:%M:%SZ)" + + if [ -n "$dry_run" ] || [ -n "$verbose" ]; then + printf "%s\n" "$cmd" + fi + + if [ -z "$dry_run" ]; then + $cmd + fi + done +} + +prune_snapshots() { + for dataset in "$@"; do + if [ -n "$recursive" ]; then + for filesystem in $(zfs list -t filesystem -o name -H -r "$dataset"); do + prune_fs "$filesystem" + done + else + prune_fs "$dataset" + fi + done +} + # Selectively destroys old snapshots for the filesystem specified by $1. # Behavior is controlled by the global variables $tag, $keep, $dry_run, and # $verbose. -prune() { +prune_fs() { snapshots=$(zfs list -t snapshot -o name -S name -H "$1") to_delete=$(printf "%s\n" "$snapshots" | grep "@${tag}-" | tail -n +"$((keep + 1))") for s in $to_delete; do @@ -83,6 +150,20 @@ prune() { done } +list_snapshots() { + cmd="zfs list" + if [ -n "$recursive" ]; then + cmd="$cmd -r" + fi + snapshots=$($cmd -t snapshot -o name -s name -H "$@") + + if [ -n "$tag" ]; then + printf "%s\n" "$snapshots" | grep "@${tag}-" + else + printf "%s\n" "$snapshots" + fi +} + while getopts t:k:cplrknvh name; do case $name in t) tag="$OPTARG";; @@ -101,84 +182,16 @@ while getopts t:k:cplrknvh name; do done shift $((OPTIND - 1)) -if [ -z "$create" ] && [ -z "$prune" ] && [ -z "$list" ]; then - printf "At least one of -c, -p, and -l must be specified.\n" - usage - exit 1 -fi - -if [ "$#" -eq 0 ] && { [ -n "$create" ] || [ -n "$prune" ]; }; then - printf "At least one dataset must be specified\n" - usage - exit 1 -fi - -if { [ -n "$create" ] || [ -n "$prune" ]; } && [ -z "$tag" ]; then - printf "Missing -t option\n" - usage - exit 1 -fi - -if [ -n "$prune" ] && [ -z "$keep" ]; then - printf "Missing -k option\n" - usage - exit 1 -fi - -if [ -z "$prune" ] && [ -n "$keep" ]; then - printf "\-k option is only valid with -p\n" - usage - exit 1 -fi - -create_cmd='zfs snapshot' -if [ -n "$recursive" ]; then - create_cmd="$create_cmd -r" -fi -readonly create_cmd +check_args "$@" -# Create snapshots. if [ -n "$create" ]; then - for dataset in "$@"; do - # FreeBSD's date -I option uses a "+00:00" suffix rather than "Z", and - # the + character is illegal in snapshot names, so we have to specify - # the format manually. - cmd="$create_cmd ${dataset}@${tag}-$(date -z utc +%Y-%m-%dT%H:%M:%SZ)" - - if [ -n "$dry_run" ] || [ -n "$verbose" ]; then - printf "%s\n" "$cmd" - fi - - if [ -z "$dry_run" ]; then - $cmd - fi - done + create_snapshots "$@" fi -# Prune snapshots. if [ -n "$prune" ]; then - for dataset in "$@"; do - if [ -n "$recursive" ]; then - for filesystem in $(zfs list -t filesystem -o name -H -r "$dataset"); do - prune "$filesystem" - done - else - prune "$dataset" - fi - done + prune_snapshots "$@" fi -# List snapshots. if [ -n "$list" ]; then - cmd="zfs list" - if [ -n "$recursive" ]; then - cmd="$cmd -r" - fi - snapshots=$($cmd -t snapshot -o name -s name -H "$@") - - if [ -n "$tag" ]; then - printf "%s\n" "$snapshots" | grep "@${tag}-" - else - printf "%s\n" "$snapshots" - fi + list_snapshots "$@" fi |