Вопрос или проблема
Хотя сравнение смонтированных снимков может работать, это может быть ужасно медленно во многих случаях.
Существует ли специфическая функция для btrfs для сравнения снимков? (Мне не удалось найти ничего в документации)
btrfs send
, который появился в Linux 3.6 (2012), “генерирует поток изменений между двумя снимками подтома.” Вы можете использовать его просто для быстрой проверки метаданных, добавив флаг --no-data
.
btrfs send --no-data -p /snapshots/parent /snapshots/child
Обычно вы бы убрали флаг --no-data
и пропустили вывод в btrfs receive
, чтобы выполнять инкрементальные резервные копии. Например, если /snapshots/parent
уже существует в /backup/snapshots/parent
, btrfs send
будет передавать только те изменения в файловую систему /backup
:
btrfs send -p /snapshots/parent /snapshots/child | btrfs receive /backup/snapshots
Я использую стабильную версию Debian, которая имеет не имела btrfs send
, поэтому я искал решение с использованием btrfs subvolume find-new
.
Обновление:
btrfs send
был добавлен в Linux 3.6, который был выпущен в 2012 году и включен в стабильную версию Debian к 2015 году.
Если у вас есть snapshot1 и snapshot2, и вы хотите узнать, что изменилось в более позднем, snapshot 2, с тех пор как был сделан snapshot1, вы можете использовать скрипт ниже, который предоставляет
btrfs-diff oldsnapshot/ newsnapshot/
который перечислит все файлы, измененные в newsnapshot/ с момента oldsnapshot/.
#!/bin/bash
usage() { echo $@ >2; echo "Использование: $0 <старый-снимок> <новый-снимок>" >2; exit 1; }
[ $# -eq 2 ] || usage "Неправильный вызов";
SNAPSHOT_OLD=$1;
SNAPSHOT_NEW=$2;
[ -d $SNAPSHOT_OLD ] || usage "$SNAPSHOT_OLD не существует";
[ -d $SNAPSHOT_NEW ] || usage "$SNAPSHOT_NEW не существует";
OLD_TRANSID=`btrfs subvolume find-new "$SNAPSHOT_OLD" 9999999`
OLD_TRANSID=${OLD_TRANSID#transid marker was }
[ -n "$OLD_TRANSID" -a "$OLD_TRANSID" -gt 0 ] || usage "Не удалось найти поколение для $SNAPSHOT_NEW"
btrfs subvolume find-new "$SNAPSHOT_NEW" $OLD_TRANSID | sed '$d' | cut -f17- -d' ' | sort | uniq
Чтобы объяснить: btrfs subvolume find-new
находит файлы, измененные после определенного ‘поколения’ снимка. Он также сообщает текущее номер поколения.
Предостережения
например, возьмем ежедневный снимок подтома:
mkdir test && cd test
btrfs subvolume create live
date >live/foo1
date >live/bar1
btrfs subvolume snapshot live/ snap1
date >live/foo2 # новый файл
date >>live/bar1 # изменить файл
rm live/foo1 # удалить файл
btrfs subvolume snapshot live/ snap2
date >live/foo3 # новый файл
mv live/bar{1,2} # переименовать файл
rm live/foo2 # удалить файл
Что изменилось между snap1 и snap2?
$ btrfs-diff snap1/ snap2/
bar1
foo2
Итак, мы можем видеть новый файл, видеть измененный файл, но удаление не отображается. Это происходит потому, что команда выводит только существующие файлы, а не те, которые теперь не существуют.
Что изменилось между snap2 и активным подтомом?
$ btrfs-diff snap2/ live/
foo3
переименованный файл не отображается. Его данные не изменились.
Теперь, что если мы добавим данные в переименованный файл
date >>live/bar2
btrfs-diff snap2/ live/
bar2
foo3
Хорошо, это имеет смысл. Но давайте создадим новый файл
date >live/lala
btrfs-diff snap2/ live/
bar2
foo3
эй! где lala?. Если вы добавите другой файл, lala
появится. Так что это поведение немного странное. Вероятно, поэтому в вики сказано:
Подход find-new имеет серьезные ограничения и поэтому не может быть действительно использован для таких вещей, как send/receive.
Тем не менее, странности происходят, когда вы сравниваете активный подтом с предыдущим состоянием, а не когда сравниваете (только для чтения) снимки. Так что это все равно может быть полезно, если вы не хотите также идентифицировать удаленные файлы.
Текущее решение:
btrfs send --no-data -p SHAPSHOT_OLD SHAPSHOT_NEW | btrfs receive --dump | grep ^update_extent
Это поддерживается инструментом удобства снятия снимков snapper
.
sudo snapper -c config diff 445..446
Конечно, это требует, чтобы вы использовали snapper
для ваших снимков.
Эти идентификаторы снимков можно найти, используя snapper list -a
. К сожалению, на момент написания snapper не поддерживал вывод списка снимков для одной конфигурации, хотя эти номера можно найти по именам подтомов.
Утилита резервного копирования btrbk
(https://github.com/digint/btrbk) также имеет подкоманду diff
(а также extents diff
).
Ответ или решение
Btrfs предоставляет несколько способов для сравнения снимков, и одним из самых эффективных методов является команда btrfs send
. Эта команда была добавлена в ядро Linux с версии 3.6 и позволяет генерировать поток изменений между двумя снимками субтома.
Для сравнения только метаданных (без передачи данных) вы можете использовать флаг --no-data
. Команда будет выглядеть следующим образом:
btrfs send --no-data -p /snapshots/parent /snapshots/child
Стандартный вариант команды btrfs send
используется для создания инкрементных резервных копий, когда вы передаете изменения из одного снимка в другое место:
btrfs send -p /snapshots/parent /snapshots/child | btrfs receive /backup/snapshots
Если вы работаете на системе, где btrfs send
недоступен или хотите более простое решение, вы можете использовать команду btrfs subvolume find-new
. Этот метод позволяет находить изменения, произошедшие после создания определенного снимка:
btrfs subvolume find-new /path/to/old/snapshot /path/to/new/snapshot
Есть также альтернативный скрипт btrfs-diff
, который позволяет сравнивать два снимка и предоставляет список всех измененных файлов:
#!/bin/bash
usage() { echo $@ >&2; echo "Usage: $0 <older-snapshot> <newer-snapshot>" >&2; exit 1; }
[ $# -eq 2 ] || usage "Неверный вызов"
SNAPSHOT_OLD=$1
SNAPSHOT_NEW=$2
[ -d $SNAPSHOT_OLD ] || usage "$SNAPSHOT_OLD не существует"
[ -d $SNAPSHOT_NEW ] || usage "$SNAPSHOT_NEW не существует"
OLD_TRANSID=$(btrfs subvolume find-new "$SNAPSHOT_OLD" 9999999)
OLD_TRANSID=${OLD_TRANSID#transid marker was }
[ -n "$OLD_TRANSID" -a "$OLD_TRANSID" -gt 0 ] || usage "Не удалось найти поколение для $SNAPSHOT_NEW"
btrfs subvolume find-new "$SNAPSHOT_NEW" $OLD_TRANSID | sed '$d' | cut -f17- -d' ' | sort | uniq
Обратите внимание, что метод с btrfs subvolume find-new
имеет некоторые ограничения. Он не показывает удаленные файлы, так как отображает только существующие. Например, если файл был удален, он не будет виден в выводе команды.
Если вам нужно сравнить непосредственно только изменения в содержимом, и вы хотите получать информацию о самых последних изменениях по метаданным и размерам, вы можете использовать комбинацию команд:
btrfs send --no-data -p SHAPSHOT_OLD SHAPSHOT_NEW | btrfs receive --dump | grep ^update_extent
Кроме того, существует множество инструментов для работы с снимками, таких как snapper
, который упрощает процесс сравнения:
sudo snapper -c config diff 445..446
Или утилита btrbk
, которая также имеет команду diff
для сравнения снимков.
Таким образом, btrfs предлагает несколько подходов для сравнения снимков, начиная от прямых команд для сравнения до удобных скриптов и вспомогательных инструментов. Выбор подхода зависит от ваших требований и среды.