#!/bin/bash # # purge old zfs snapshots # work on Solaris 10, not tested in other environment # by Igor Velkov # v 0.2.1 # based on snap_zfs by trevor.pretty@sun.com SCRIPT_NAME=$0 FILESYSTEM=$1 ID=/usr/xpg4/bin/id ZFS=/usr/sbin/zfs NOW="date +%Y-%m-%d.%H:%M:%S " DEBUG=N # very bad!!!!! # get the current date in unixtime format DATE=`/usr/bin/truss /usr/bin/date 2>&1 | nawk -F= '/^time\(\)/ {gsub(/ /,"",$2);print $2}'` ## Usage # Usage() { echo "Recursively removes all snapshots of filesystem " echo "older min_age, or between (min_age..max_age)" echo "Usage: $SCRIPT_NAME filesystem @snapprefix min_age [max_age]" echo "" echo "Examples" echo " $SCRIPT_NAME pool/name @snap 3" echo " $SCRIPT_NAME pool/name @snap 3 10" echo "" echo "Note: The filesystem cannot have a trailing \"/\"" echo "snapprefix must always start with \"@\"" echo "" exit 1 } ########### Main Part ################### ## Check Usage # if [ $# -lt 3 ]; then echo 'You have to provide at least 3 arguments' Usage fi # check if parameter 3 is number # [0-9]+ case "$3" in *[^0-9]*) echo '3rd argument must be a number' Usage exit 1 ;; *) MIN="$3" ;; esac # check if parameter 4 is present and is number # [0-9]+ case "$4" in *[^0-9]*) echo '4rd argument must be a number if present' Usage exit 1 ;; # 4rd parametr is number [0-9]*) MAX=$4 ;; *) ;; esac # sheck for snapshot pattern starts with "@" ant not contain more @ # it must for not erase filesystem if no "@" will be supplied SNAPPTN="$2" if [ "@${SNAPPTN#@}" != "$SNAPPTN" ]; then echo "Second parameter must start with @ and not contain \"@\" more" Usage fi ## See if we have right authorization: Either we are root or allowed to manage ZFS # WHO=`/usr/xpg4/bin/id -n -u` PROF=`/bin/profiles | grep "ZFS File System Management"` if [ "$PROF" != "ZFS File System Management" ]; then if [ "$WHO" != "root" ]; then echo "$SCRIPT_NAME: ERROR: you are not authorized to run this script." exit 1 fi fi # get list in format fsname, used bytes, creation time, mountpoint # we will work only where type=snapshot $ZFS get -H -o value -rp name,used,creation,type "$FILESYSTEM" \ | sed '$!N;s/\n/ /' | sed '$!N;s/\n/ /' | grep "$SNAPPTN" \ | while read SNNAME SNUSED SNTIME SNTYPE; do if [ "$DEBUG" = 'Y' ] ; then echo "$SNNAME $SNUSED $SNTIME $SNTYPE" fi #work only with snapshots, not filesystem or something other if [ "$SNTYPE" != 'snapshot' ]; then if [ "$DEBUG" = 'Y' ] ; then echo "type is \"$SNTYPE\", not processed" fi continue; fi # AGE is snapshot age in days, count from unixtime dy /sec in min/min in a hour/hour in a day AGE=`expr \( $DATE - $SNTIME \) / 60 / 60 / 24` # target expression (!$MAX & ($AGE >= $MIN)) | ($MAX & ($AGE < $MAX) & ($AGE >= $MIN)) # inverse: not remove if $AGE < $MIN or (isset($MAX) and $AGE>$MAX) ERASE=Y if [ "$AGE" -lt "$MIN" ]; then ERASE=N elif [ "$MAX" ]; then if [ "$AGE" -gt "$MAX" ]; then ERASE="N" fi fi if [ "$DEBUG" = 'Y' ] ; then echo "snap:$SNNAME snaptime:$SNAPTIME age:$AGE min:$MIN max:$MAX erase:$ERASE" fi if [ "$ERASE" != 'N' ]; then if [ "$DEBUG" = 'Y' ] ; then echo "want run zfs remove $SNNAME" else # not using -R swich to protect child objects if exists $ZFS destroy "$SNNAME" if [ $? -gt 0 ] ; then echo "error destroying $SNNAME" else echo "$SNNAME destroyed" fi fi fi done exit