-
-
Save SkyWriter/58e36bfaa9eea1d36460 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
fsWithSnapshots=$(zfs list -Hr -t snapshot tank/share |grep '@' |cut -d '@' -f 1 |uniq) | |
for fs in $fsWithSnapshots ; do | |
# Changed to now sort newest to oldest. This will mean that newer snapshots without deltas will get removed. | |
emptySnapshot=$(zfs list -Hr -d1 -t snapshot -o name,used -S creation $fs |sed '$d' |awk ' $2 == "0B" { print $1 }' ) | |
for snapshot in $emptySnapshot ; do | |
# Added safety check. Verify the size of the snapshot prior to destroying it | |
used=$(zfs list -Hr -d1 -t snapshot -o used $snapshot) | |
if [[ $used != "0B" ]]; then | |
continue | |
fi | |
echo "Destroying empty snapshot $snapshot" | |
zfs destroy $snapshot | |
done | |
done |
FYI this script is broken, and will delete non-empty snapshots. See the explanation here: https://www.mail-archive.com/zfs-discuss@opensolaris.org/msg17752.html
This works fine and carefully deletes zero sized snaps one by one
https://github.com/fracai/zfs-rollup/blob/master/clearempty.py
zfs list -t snapshot | awk '$2 == 0 {print $1}' | xargs -r -n 1 /sbin/zfs destroy
change line 7 to
emptySnapshot=$(zfs list -Hr -d1 -t snapshot -o name,used -s creation $fs | sed '$d' | awk ' $2 == "0B" { print $1 }' )
and it works again 👍
FYI this script is broken, and will delete non-empty snapshots. See the explanation here: https://www.mail-archive.com/zfs-discuss@opensolaris.org/msg17752.html
^ This is correct. The script will delete snapshots that aren't actually zero bytes.
Here's a revised version -- it should avoid deleting snapshots that actually have data, and should preserve the first snapshot in which the change appeared:
#!/bin/bash
fsWithSnapshots=$(zfs list -Hr -t snapshot tank/share |grep '@' |cut -d '@' -f 1 |uniq)
for fs in $fsWithSnapshots ; do
# Changed to now sort newest to oldest. This will mean that newer snapshots without deltas will get removed.
emptySnapshot=$(zfs list -Hr -d1 -t snapshot -o name,used -S creation $fs |sed '$d' |awk ' $2 == "0B" { print $1 }' )
for snapshot in $emptySnapshot ; do
# Added safety check. Verify the size of the snapshot prior to destroying it
used=$(zfs list -Hr -d1 -t snapshot -o used $snapshot)
if [[ $used != "0B" ]]; then
continue
fi
echo "Destroying empty snapshot $snapshot"
zfs destroy $snapshot
done
done
Thanks! I have updated the gist (especially now that it attracts so many people!) as well as my own scripts.
is still safe this script?
Hi
The reason this script (and surprisingly, all other scripts which fulfil the same task) has to iterate over the snapshots in reverse order and recheck the size is, that you are using the "used" property instead of the "written" property. The latter is exactly then zero when the snapshot is empty. And in case you wonder, it's from 2011: https://www.illumos.org/issues/1645
zfs create zroot/snaptest
zfs set mountpoint=/snaptest zroot/snaptest
cd /snaptest/dd if=/dev/random bs=1M count=1 of=a
zfs snap zroot/snaptest@1dd if=/dev/random bs=1M count=1 of=b
zfs snap zroot/snaptest@2zfs snap zroot/snaptest@3
dd if=/dev/random bs=1M count=1 of=c
zfs snap zroot/snaptest@4zfs snap zroot/snaptest@5
dd if=/dev/random bs=1M count=1 of=d
rm a
zfs snap zroot/snaptest@6rm b
rm c
zfs snap zroot/snaptest@7zfs snap zroot/snaptest@8
rm d
zfs snap zroot/snaptest@9zfs list -o name,used,written zroot/snaptest -r -tall
NAME USED WRITTEN
zroot/snaptest 4.44M 0
zroot/snaptest@1 64K 1.10M
zroot/snaptest@2 0B 1.07M
zroot/snaptest@3 0B 0
zroot/snaptest@4 0B 1.07M
zroot/snaptest@5 0B 0
zroot/snaptest@6 64K 1.07M
zroot/snaptest@7 0B 64K
zroot/snaptest@8 0B 0
zroot/snaptest@9 0B 64K
Here's a revised version -- it should avoid deleting snapshots that actually have data, and should preserve the first snapshot in which the change appeared:
jimsalterjrs/sanoid#616 (comment)
https://www.reddit.com/r/zfs/comments/ja1k7n/sanoid_dont_create_empty_0b_snapshots/
Thanks - very useful!
Changed the 'tank/share' to my vdev/share and worked!