Skip to content

Instantly share code, notes, and snippets.

@mbreese
Last active May 13, 2025 06:52
Show Gist options
  • Save mbreese/f4662d59577f294c646fa7da54d00e8c to your computer and use it in GitHub Desktop.
Save mbreese/f4662d59577f294c646fa7da54d00e8c to your computer and use it in GitHub Desktop.
This is a script to take daily snapshots of a ZFS filesystem (and prune older snapshots).
#!/bin/bash
#
# This will by default take snapshots of all zfs filesystems,
# but could be adapted to only pull specific ones. This script
# will also rotate snapshots, removing those that are older
# than 2 weeks.
#
CURDATE=$(date +%Y%m%d)
TWOWEEKSAGO=$(date -d'2 weeks ago' +%Y%m%d)
create_snapshot() {
if [ "$(/sbin/zfs list -tsnapshot | grep $1@$CURDATE)" = "" ]; then
/sbin/zfs snapshot $1@$CURDATE
fi
}
prune_old () {
if [ "$(/sbin/zfs list -tsnapshot | grep "$1@")" != "" ]; then
for f in $(/sbin/zfs list -tsnapshot | grep "$1@" | awk '{print $1}'); do
echo ">>> $f"
SNAPDATE=$(echo $f | sed -e 's/@/ /' | awk '{print $2}')
if [ $SNAPDATE -lt $TWOWEEKSAGO ]; then
# echo "destroying snapshot $f"
/sbin/zfs destroy $f
fi
done
fi
}
FS=$(/sbin/zfs list | awk '{print $1}' | tail -n+2)
for f in $FS; do
create_snapshot $f
prune_old $f 2>/dev/null
done
#!/bin/bash
#
DATE="$(date +%Y%m%d)"
TWOWEEKS="$(date -d '14 days ago' '+%Y%m%d')"
PRUNE=0
if [ "$1" == "-prune" ]; then
PRUNE=1
shift
fi
snapshot() {
zfs snapshot tank/data@$DATE
if [ $PRUNE -eq 1 ]; then
for line in $(zfs list -t snapshot | grep '^tank/data@' | sed -e 's/@/ /' | awk '{print $2}'); do
if [ $line -lt $TWOWEEKS ];then
zfs destroy tank/data@$line
fi
done
fi
}
case "$1" in
list)
zfs list -t snapshot
;;
create)
snapshot
;;
*)
echo "Usage $0 [-prune] [list|create]"
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment