Skip to content

Instantly share code, notes, and snippets.

@iav
Created September 23, 2019 12:54
Show Gist options
  • Save iav/3298850ffdfaa7efe7f977162fa3143e to your computer and use it in GitHub Desktop.
Save iav/3298850ffdfaa7efe7f977162fa3143e to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# purge old zfs snapshots
# work on Solaris 10, not tested in other environment
# by Igor Velkov <dober-aeons.lv>
# 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}'`
DATE=`perl -e "print time"`
## 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment