ZFS の snapshot をローテートするスクリプトを書いた

ZFS はスナップショットを高速に撮れるので、cron などで定期的に撮っている人も多いでしょう。
しかしそのままでは、スナップショットがどんどん溜まってしまいます。
そこで、適宜削除するスクリプトを作ってみました。

手動で作成したスナップショットを消してしまわないように作りました。

  • 一応、動作確認環境
    • FreeBSD 8.2-RELEASE amd64

スクリプト

snapshotrotate.sh

#!/bin/sh
#
# 20110529
# rotate snapshots
#
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
export PATH


#
# usage
#
if [ "${1}" = "" ]
then
{
  echo "usage:"
  echo "${0} /path/to/config"
  exit 1
}
fi


#
# define
#
PREFIX="autosnapshot_"
TIMESTAMP=`date +%Y%m%d_%H%M%S`
FILESYSTEMS=`cat ${1}`
ZFSOPTS="-r"            # (*1)
GENERATION=6            # (*2)


#
# take snapshots
#
for f in `echo "${FILESYSTEMS}"`; do
  zfs snapshot ${ZFSOPTS} ${f}@${PREFIX}${TIMESTAMP}
done


#
# delete old snapshots
#
for f in `echo "${FILESYSTEMS}"`; do
  SNAPSHOTS=`zfs list -t snapshot | grep "${f}@${PREFIX}" | cut -d" " -f1` # (*3)
  DELLIST=`echo "${SNAPSHOTS}" | sort -r | sed -e "1,${GENERATION}d"`      # (*4)

  for d in `echo "${DELLIST}"`; do
    zfs destroy ${ZFSOPTS} ${d}
  done
done

解説のようなもの

*1
下の階層のスナップショットも撮りたい場合、"-r" を指定。そうでない場合は、"" を指定。

*2
残したいスナップショットの世代数を指定。

*3
スナップショットをリストアップし、grep で <ファイルシステム名>@<PREFIX> であるものを抜き出す。

*4
新しい順に並び替え、sed で先頭から世代数分だけ削る。(削除対象から外す。)

使い方

以下のように、スナップショットを撮りたいファイルシステム名を適当なファイルに記述し、そのファイルをスクリプトの第一引数に与えてください。
繰り返し実行すると、古いものが消えていくはずです。

cron に登録して、自動実行させて下さい。

# echo zroot > /etc/snapshotrotate.conf
# echo testpool0/sub >> /etc/snapshotrotate.conf
# sh /root/bin/snapshotrotate.sh /etc/snapshotrotate.conf