6
3

More than 5 years have passed since last update.

ZFSのsnapshotをまとめて削除する

Last updated at Posted at 2018-12-27

ZFS snapshotの浪費

ZFSで定期的にsnapshotをとりながら長期間運用していると、snapshotに不要なデータがたまり、ファイルを削除しても実体はsnapshotに残るのでディスクの空き容量が増えないということもよくあります。

$ cd ~/tmp
$ ls
Data
$ du -s Data
528     Data
$ rm -rf *
$ ls
 (ファイルは何もない)
$ df -h .
Filesystem               Size    Used   Avail Capacity  Mounted on
zvol0/home/minmin/tmp    2.2T    228K    2.2T     0%    /home/minmin/tmp
(ディスク使用量は 見かけ上はディレクトリ分のみ)
$ zfs list -o space zvol0/home/minmin/tmp
NAME                   AVAIL   USED  USEDSNAP  USEDDS  USEDREFRESERV  USEDCHILD
zvol0/home/minmin/tmp  2.16T  1.01G     1.01G    227K              0          0
(実際は zfsとして 1GB程 snapshot が消費)

このような状態で過去のsnapshotのデータが不要であればsnapshotを削除しないとディスク容量が無駄になります。

zfs destroy で snapshot を指定するときの %

指定したZFSのsnapshotをまとめて削除するシェルスクリプトを作るかなと思い、改めて man zfs していて気づきました。

    zfs destroy [-dnpRrv] filesystem|volume@snap[%snap][,snap[%snap]][,...]

削除のときは % でsnapshotの範囲を指定できるわけで、最古のsnapshotと最新のsnapshotを調べて % で挟むめば、その間の不要な snapshot をまとめて削除できます。

zfs destroy ZFS@oldest_snap%newest_snapshot

他にも複数の snapshot のうち不要なものを個別に指定する , (カンマ) のオプションがありますね。これらを活用すると、snapshotを一つづつ削除するのに比べると、かなり効率がよさそうです。

ZFS snapshot をまとめて削除するコマンド

zfs-purge-snapshot というコマンドを作ってみました。使い方は

$ zfs-purge-snapshot zvol0/home/minmin/tmp 

のように、引数にzfsのfilesystemを指定します。

実際に使ってみた例です

$ df -h .
Filesystem               Size    Used   Avail Capacity  Mounted on
zvol0/home/minmin/tmp    2.2T    228K    2.2T     0%    /home/minmin/tmp
$ zfs list -o space zvol0/home/minmin/tmp
NAME                   AVAIL   USED  USEDSNAP  USEDDS  USEDREFRESERV  USEDCHILD
zvol0/home/minmin/tmp  2.16T  1.01G     1.01G    227K              0          0
$ zfs-purge-snapshot zvol0/home/minmin/tmp
$ zfs list -o space zvol0/home/minmin/tmp
NAME                   AVAIL   USED  USEDSNAP  USEDDS  USEDREFRESERV  USEDCHILD
zvol0/home/minmin/tmp  2.16T   227K         0    227K              0          0

このとおり、df と zfs list それぞれの使用量が一致しました。

プログラムは以下の通りです。

#!/bin/sh

PATH=$PATH:/sbin:/usr/sbin

ZFS_list_snap='zfs list -H -o name -d 1 -t snapshot'

if [ $# -le 0 ]; then
        echo "Usage: ${0##*/} zfs [zfs ...]" 1>&2
        exit 2
fi

for fs in "$@"; do
        if [ $(${ZFS_list_snap} "${fs}" | wc -l) = 0 ]; then
                continue
        fi
        snap0=$(${ZFS_list_snap} "${fs}" | head -1)
        snap1=$(${ZFS_list_snap} "${fs}" | tail -1 | sed 's/.*@//')
        zfs destroy "${snap0}%${snap1}" || exit
done
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3