Skip to content

Instantly share code, notes, and snippets.

@minagi-yu
Last active April 2, 2026 10:59
Show Gist options
  • Select an option

  • Save minagi-yu/4bc4fe6fbc5bf4dbc2c57facf88f34e8 to your computer and use it in GitHub Desktop.

Select an option

Save minagi-yu/4bc4fe6fbc5bf4dbc2c57facf88f34e8 to your computer and use it in GitHub Desktop.
Shell script to take periodically ZFS snapshot
#!/bin/sh
set -eu
# crontab
# ---
# */5 * * * * z-snap.sh minutely
# 1 * * * * z-snap.sh hourly
# 2 3 * * * z-snap.sh daily
# 3 4 * * 0 z-snap.sh weekly
# 4 5 1 * * z-snap.sh monthly
monthly_count=12
weekly_count=4
daily_count=7
hourly_count=24
minutely_count=3
pools="tank"
PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"
time_tag=$1
case $time_tag in
"monthly")
count=$monthly_count;;
"weekly")
count=$weekly_count;;
"daily")
count=$daily_count;;
"hourly")
count=$hourly_count;;
"minutely")
count=$minutely_count;;
*)
exit 1;;
esac
count=$((count + 1))
for pool in $pools
do
snapname="${time_tag}_$(date '+%Y-%m-%dT%H:%M:%S')"
zfs snapshot -r "$pool@$snapname" || exit 1
expired=$(
zfs list -H -t snapshot -o name -d 1 "$pool" |
grep "^${pool}@${time_tag}_" |
sort -r |
tail -n +"$count"
)
if [ -n "$expired" ]; then
for e in $expired
do
zfs destroy -nv -r "$e" || exit 1
done
fi
done
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment