Как удалить все, кроме последних [n] снимков ZFS?

В настоящее время я делаю моментальные снимки своего сетевого хранилища на базе ZFS еженедельно и ночью - процесс, который несколько раз спасал мою задницу. Однако, хотя создание снимков происходит автоматически (с помощью cron), удаление старых снимков по-прежнему выполняется вручную. Очевидно, есть риск, что если меня собьет автобус или если ручная задача не будет выполнена, на NAS закончится место на диске.

Есть ли у кого-нибудь хорошие способы / сценарии, которые они используют для управления количеством моментальных снимков, хранящихся на их системах ZFS? В идеале мне бы хотелось получить сценарий, который перебирает все снимки для данной файловой системы ZFS и удаляет все, кроме последних n снимков для этой файловой системы.

Например, у меня есть две файловые системы, одна называется tank, а другая sastank. Снимки именуются датой их создания: sastank@AutoD-2011-12-13, поэтому простая команда sort должна перечислить их по порядку. Я хочу сохранить ежедневные снимки за последние две недели на tank, но только снимки за последние два дня на sastank.

24
задан 14 December 2011 в 14:27
9 ответов

Вы можете найти что-то вроде этого, что немного проще

zfs list -t snapshot -o name | grep ^tank@Auto | tac | tail -n +16 | xargs -n 1 zfs destroy -r
  • вывести список снимков (только имена) с фильтром zfs list -t snaphot -o name
  • , чтобы сохранить только те, которые соответствуют tank @ Auto с grep ^ tank @ Auto
  • перевернуть список (ранее отсортированный от самого старого к самому новому) с помощью tac
  • ограничить вывод до 16-го самого старого результата, а затем с помощью tail -n +16
  • , затем уничтожить с помощью xargs -n 1 zfs destroy -vr

удаление снимков в обратном порядке предположительно более эффективно.

или сортировка в обратном порядке создания

zfs list -t snapshot -o name -S creation | grep ^tank@Auto | tail -n +16 | xargs -n 1 zfs destroy -vr

Протестируйте это с помощью ... | xargs -n 1 echo

35
ответ дан 28 November 2019 в 20:14

Возможно, я решил эту проблему с помощью какой-нибудь баш-фу.

 zfs list -t snapshot -o name | grep ^tank@AutoD- | sort -r | wc -l | xargs -n 1 expr -$NUM_TO_KEEP + | tr -d '\n' | xargs -0 -i bash -c "zfs list -t snapshot -o name | grep ^tank@AutoD- | sort -r | tail -n{} | sort |xargs -t -n 1 zfs destroy -r"

Вау. Это так неправильно.

3
ответ дан 28 November 2019 в 20:14

Growse's не работал на OpenIndiana для меня. Он не понимает -0 для xargs.

При использовании sort имейте в виду, что он сортирует в алфавитном порядке, что может быть нежелательно, поскольку вы, вероятно, хотите найти самые последние.

Вот код, который удалит все, кроме последние снимки.

Удалите «эхо», чтобы начать работу.

RETENTION=5
FS=tank1/test
SNAPNAME=daily-

zfs list -t snapshot -o name | grep ^$FS@${SNAPNAME} |  sed -n -e :a -e '1,${RETENTION}!{P;N;D;};N;ba' | xargs -n 1 echo zfs destroy -r

Источники: http://sed.sourceforge.net/sed1line.txt

5
ответ дан 28 November 2019 в 20:14

Путь для головы необходим в Solaris, но он должен работать без пути в других дистрибутивах.

retention=14
dataset=vmstorage-17/824

zfs list -rt snap -H -o name ${dataset} | \
/usr/gnu/bin/head -n -${retention} | xargs -n 1 zfs destroy -r
1
ответ дан 28 November 2019 в 20:14

Более общий случай получения самого последнего снимка на основе по дате создания, а не по имени.

zfs list -H -t snapshot -o name -S creation | head -1

Область действия связана с определенным именем файловой системы TestOne

zfs list -H -t snapshot -o name -S creation -d1 TestOne | head -1

-H : Без заголовка, поэтому первая строка представляет собой имя снимка

-t snapshot : Список снимков (список может содержать другие вещи, такие как пулы и тома)

-o name : отображение свойства имени снимка.

-S создание : заглавная S обозначает сортировку по убыванию , основанную на времени создания. Это помещает самый последний снимок в первую строку.

-d1 TestOne : Говорит, что включает детей, что кажется сбивающим с толку, но это связано с тем, что для этой команды снимки TestOne являются дочерними. При этом НЕ будут перечислены снимки томов в TestOne, такие как TestOne /SubVol @ someSnapshot .

| head -1 : труба к голове и возврат только первой линии.

19
ответ дан 28 November 2019 в 20:14

Это полностью не отвечает на сам вопрос, но не забывайте, что вы можете удалять диапазоны снимков.

zfs destroy zpool1 / dataset @ 20160918% 20161107

Уничтожит все снимки с «20160918» по «20161107» включительно. Любой конец может быть оставлен пустым, что означает «самый старый» или «самый новый». Так что вы можете придумать что-то, что вычисляет "n", а затем уничтожить "...% n" ..

Простите, что воскресил старый вопрос.

8
ответ дан 28 November 2019 в 20:14

Вы также можете посмотреть zfs-prune-snapshots .

Удаление снимков из одного или нескольких zpools, соответствующих заданным критериям.

Он имеет довольно надежный механизм, основанный на времени, для удаления снимков, пример из документации:

Удаление снимков старше двух месяцев в пуле резервуаров, который заканчивается со строкой "_frequent"

zfs-prune-snapshots -s '_frequent' 2M tank

4
ответ дан 9 January 2020 в 19:18

Просто хотел поделиться тем, как я делаю это во FreeBSD и OmniOS:

Получить количество снимков:

zfs list -t snapshot -o name | grep ^tank@Auto | wc -l
141

Вычесть число, которое вы хотите оставить для n (например, 30 для месяца последних ежедневных снимков):

zfs list -t snapshot -o name | grep ^tank@Auto |  head -n +111 | xargs -n 1 zfs destroy -vr

Обратите внимание, как я заменил tail на head для удаления в порядке от самого старого к самому новому, так как во FreeBSD нет команды tac

Вот и все! У меня отлично работает...

1
ответ дан 29 July 2020 в 21:02

Определить два последних моментальных снимка для заданного набора данных (создание, от новых к старым)

zfs_latest=`zfs list -H -t snapshot -o name -S creation | grep ^tank/example_dataset@ | head -2`

Определить ВСЕ снимки для данного набора данных (создание, от новых к старым)

zfs_delete=`zfs list -H -t snapshot -o name -S creation | grep ^tanks/example_dataset@`

Удалить последние снимки из всего набора; создание списка снимков для удаления.

for keep_snap in ${zfs_latest[@]}; do
  zfs_delete=( "${zfs_delete[@]/$keep_snap}" );
done

Удалить старые снимки

for snap in ${zfs_delete[@]}; do
  zfs destroy ${snap}
done
1
ответ дан 6 July 2021 в 23:17

Теги

Похожие вопросы