#! /usr/bin/env perl # Simplified BSD License (FreeBSD License) # # Copyright (c) 2026, Daily Data Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # cleanSnaps - Wrapper script for automated ZFS snapshot cleanup # # PURPOSE: # This is a customizable wrapper script that calls the cleanSnaps utility to remove # expired ZFS snapshots based on TTL (Time To Live) retention policies embedded in # snapshot names. # # USAGE: # Typically executed automatically by sneakernet during the cleanup phase after # replication completes on the target server. Can also be run manually for testing. # # IMPORTANT - CUSTOMIZATION: # This script is designed to be copied and customized per installation: # 1. Copy this file to a new name (e.g., cleanSnaps.mysite) to preserve during updates # 2. Modify the filesystem name ('storage' below) to match your environment # 3. Adjust retention policies and options as needed # 4. Test in report mode first (remove -f flag) before enabling deletion # # WARNING - DESTRUCTIVE OPERATION: # By default, this script uses the -f (force) flag which WILL DELETE snapshots. # Snapshots that exceed their TTL (encoded in snapshot name) will be permanently removed. # Always test without -f flag first to see what would be deleted. # # EXECUTION CONTEXT: # When executed by sneakernet on the target server: # - Script is read from transport drive, decrypted, and executed via eval() # - Current working directory may not be predictable # - The script must return output (not print) for logging by sneakernet # - Exit codes and errors should be handled gracefully # # SNAPSHOT NAMING REQUIREMENTS: # Snapshots must follow naming conventions with TTL suffixes for automatic cleanup: # Examples: pool/fs@2025-12-15_7d (7-day retention) # pool/fs@2025-12-15_3m (3-month retention) # See ../cleanSnaps/cleanSnaps.md for complete documentation on TTL formats. # # Author: R. W. Rodolico # Version: 1.0 # Created: 2026-01-16 use strict; use warnings; use FindBin; # Determine path to cleanSnaps utility # Uses FindBin to locate this script's directory, then navigates to ../cleanSnaps # NOTE: If this script is executed from a different location (e.g., by sneakernet), # the relative path may not resolve correctly. Adjust if needed. my $cleanSnapsPath = "$FindBin::Bin/../cleanSnaps/cleanSnaps"; my $errors = []; # Verify cleanSnaps utility exists before attempting to run unless (-x $cleanSnapsPath) { push @$errors, "cleanSnaps utility not found or not executable at: $cleanSnapsPath"; return ('', join("\n", @$errors)); } # Execute cleanSnaps with default configuration # -f flag: Force mode - WILL DELETE snapshots that exceed their TTL # 'storage': Filesystem to process - CUSTOMIZE THIS for your environment # # For initial testing, remove -f flag to run in report-only mode: # my $output = `$cleanSnapsPath storage`; my $output = `$cleanSnapsPath -f storage`; # Capture any errors from execution if ($? != 0) { my $exit_code = $? >> 8; push @$errors, "ERROR: cleanSnaps exited with code $exit_code"; } # Return output to caller (sneakernet logs this) return ($output, join("\n", @$errors)); # CUSTOMIZATION EXAMPLES: # Uncomment and modify as needed for your environment # # Example 1: Process multiple filesystems # my $output1 = `$cleanSnapsPath -f pool1/data`; # my $output2 = `$cleanSnapsPath -f pool2/backups`; # return "$output1\n$output2"; # # Example 2: Use time-shift for testing (simulate 6 months in the future) # my $output = `$cleanSnapsPath -t 6m -f storage`; # # Example 3: Clean only malformed snapshots (ignore TTL) # my $output = `$cleanSnapsPath -u -f storage`; # # Example 4: Verbose output for detailed logging # my $output = `$cleanSnapsPath -v -f storage`; # # Example 5: Report mode only (no deletion) # my $output = `$cleanSnapsPath storage`; # # For complete option documentation, run: cleanSnaps --help # Or see: ../cleanSnaps/cleanSnaps.md