summaryrefslogtreecommitdiff
path: root/dotfiles/system/.local/bin/zfssnapshot
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/system/.local/bin/zfssnapshot')
-rwxr-xr-xdotfiles/system/.local/bin/zfssnapshot103
1 files changed, 103 insertions, 0 deletions
diff --git a/dotfiles/system/.local/bin/zfssnapshot b/dotfiles/system/.local/bin/zfssnapshot
new file mode 100755
index 0000000..b715722
--- /dev/null
+++ b/dotfiles/system/.local/bin/zfssnapshot
@@ -0,0 +1,103 @@
+#!/bin/env bash
+# Craig Jennings <c@cjennings.net>
+# Create a ZFS snapshot across all datasets with a dated, descriptive name.
+
+set -euo pipefail
+
+# Usage info
+show_help() {
+ cat << EOF
+Usage: ${0##*/} [-h] [DESCRIPTION]
+Create a ZFS snapshot across all datasets.
+
+ -h display this help and exit
+ DESCRIPTION short description for the snapshot (optional, will prompt if omitted)
+
+Snapshot names are formatted as: YYYY-MM-DD-description
+Only alphanumeric characters, hyphens, and underscores are allowed in descriptions.
+Spaces are converted to hyphens automatically.
+
+Examples:
+ ${0##*/} before-upgrade
+ ${0##*/} "pre system update"
+ ${0##*/} # prompts for description
+EOF
+}
+
+# Check for ZFS
+if ! command -v zfs &> /dev/null; then
+ echo "Error: zfs command not found. Is ZFS installed?"
+ exit 1
+fi
+
+# Check for root/sudo
+if [ "$EUID" -ne 0 ]; then
+ echo "Error: This script must be run as root (use sudo)"
+ exit 1
+fi
+
+# Parse arguments
+while getopts ":h" opt; do
+ case ${opt} in
+ h)
+ show_help
+ exit 0
+ ;;
+ \?)
+ echo "Invalid option: -$OPTARG" >&2
+ show_help
+ exit 1
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+# Get description from argument or prompt
+if [ $# -ge 1 ]; then
+ description="$*"
+else
+ read -r -p "Enter snapshot description: " description
+ if [ -z "$description" ]; then
+ echo "Error: Description cannot be empty"
+ exit 1
+ fi
+fi
+
+# Sanitize description: convert spaces to hyphens, lowercase
+description=$(echo "$description" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
+
+# Validate description: only allow alphanumeric, hyphens, underscores
+if [[ ! "$description" =~ ^[a-z0-9_-]+$ ]]; then
+ echo "Error: Description contains invalid characters"
+ echo "Only letters, numbers, hyphens, and underscores are allowed"
+ echo "Sanitized input was: $description"
+ exit 1
+fi
+
+# Create snapshot name with date prefix
+date_prefix=$(date +%Y-%m-%d)
+snapshot_name="${date_prefix}-${description}"
+
+# Get all pools
+pools=$(zpool list -H -o name)
+
+if [ -z "$pools" ]; then
+ echo "Error: No ZFS pools found"
+ exit 1
+fi
+
+echo "Creating snapshots with name: @${snapshot_name}"
+echo ""
+
+# Create recursive snapshots on each pool
+for pool in $pools; do
+ echo "Snapshotting pool: $pool"
+ if zfs snapshot -r "${pool}@${snapshot_name}"; then
+ echo " ✓ Created ${pool}@${snapshot_name} (recursive)"
+ else
+ echo " ✗ Failed to snapshot $pool"
+ fi
+done
+
+echo ""
+echo "Snapshot complete. Verify with: zfs list -t snapshot | grep $snapshot_name"