Снапшоты Btrfs защищают от неудачного обновления, но лежат на том же диске. Если диск выйдет из строя, исчезнут и данные, и копии. Btrfs send/receive переносит снапшоты на другой носитель и умеет передавать только изменения — это дешёвый инкрементальный бэкап без сторонних агентов.

Как работает передача

btrfs send читает снапшот и выдаёт поток изменений в стандартный вывод. btrfs receive применяет поток на другой файловой системе и создаёт subvolume. Передавать можно только снапшоты, доступные только для чтения: иначе содержимое изменится прямо во время чтения.

Инкрементальный режим указывает родительский снапшот через -p. Принимающая сторона должна уже иметь этот родительский subvolume с тем же идентификатором. Если родителя нет, поток не применится — это главная причина ошибок при восстановлении на новом диске.

Подготовка и первый снапшот

Сначала проверьте, что источник и приёмник — Btrfs, а на приёмнике достаточно места. Снапшоты удобно складывать в отдельный subvolume, чтобы они не попадали в собственный бэкап.

btrfs subvolume list /
btrfs filesystem usage /mnt/backup
mkdir -p /home/.snapshots
btrfs subvolume snapshot -r /home /home/.snapshots/base-2026-11-06

Флаг -r делает снапшот доступным только для чтения. Проверить это можно через btrfs property get -ts. Дата в имени помогает строить цепочки, но для скриптов надёжнее отдельный файл состояния с именем последнего успешного снапшота.

btrfs property get -ts /home/.snapshots/base-2026-11-06 ro
btrfs subvolume show /home/.snapshots/base-2026-11-06 | head -20

Полная копия

Первый поток содержит все данные и может быть большим. Его отправляют на приёмник один раз, а дальше строят цепочку от него.

btrfs send /home/.snapshots/base-2026-11-06 | btrfs receive /mnt/backup
btrfs subvolume list /mnt/backup
du -sh /mnt/backup/base-2026-11-06

Приёмник создаёт каталог с тем же именем, что и снапшот. Проверьте, что subvolume виден и доступен для чтения. Если места мало, используйте сжатие потока: zstd даёт хороший компромисс скорости и степени сжатия. Сжатие на лету экономит диск и сеть, но нагружает процессор.

btrfs send /home/.snapshots/base-2026-11-06 | zstd -T0 -3 > /mnt/backup/base.zst
zstd -d -c /mnt/backup/base.zst | btrfs receive /mnt/backup

Так получается сжатый архив, который можно хранить отдельно и распаковать позже. При прямой передаче между процессами поток нельзя сжимать без распаковки на приёмнике: btrfs receive не понимает zstd и получит мусор. Для сети используйте схему с zstd -d на удалённой стороне, она показана ниже.

Инкрементальная передача

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

btrfs subvolume snapshot -r /home /home/.snapshots/2026-11-07
btrfs send -p /home/.snapshots/base-2026-11-06   /home/.snapshots/2026-11-07 | btrfs receive /mnt/backup
btrfs subvolume list -r /mnt/backup

Родитель должен существовать на обеих сторонах. Если вы удалили старый снапшот на источнике, следующая инкрементальная передача от него не построится. Поэтому цепочку планируют заранее: либо хранят базу долго, либо периодически делают новый полный снапшот и начинают цепочку заново.

Проверить, что приёмник получил именно инкремент, можно по размеру и по списку subvolume. Полный поток от базы каждый раз — не ошибка, но он снова передаст все данные.

Скрипт с ротацией

Ручные команды быстро забываются, поэтому передачу оформляют скриптом с блокировкой от параллельного запуска. Ниже — минимальный вариант без внешних зависимостей.

#!/usr/bin/env bash
set -euo pipefail
SRC=/home
DST=/mnt/backup
SNAP="$SRC/.snapshots/$(date +%F-%H%M)"
LAST=$(cat /var/lib/btrfs-last 2>/dev/null || true)
btrfs subvolume snapshot -r "$SRC" "$SNAP"
if [ -n "$LAST" ] && btrfs subvolume list "$DST" | grep -q "$(basename "$LAST")"; then
  btrfs send -p "$LAST" "$SNAP" | btrfs receive "$DST"
else
  btrfs send "$SNAP" | btrfs receive "$DST"
fi
echo "$SNAP" > /var/lib/btrfs-last

Скрипт обновляет файл состояния только после успешной передачи. Если receive упал, следующая попытка снова возьмёт прежнего родителя. Ротацию делайте отдельной задачей: удаляйте старые снапшоты и на источнике, и на приёмнике, но никогда не удаляйте родителя, на который ещё ссылается цепочка.

Передача по SSH

Сетевой вариант почти не отличается: поток идёт через ssh, а распаковка выполняется на приёмнике. Для регулярных задач настройте ключ без пароля и ограничьте команду в authorized_keys.

btrfs send -p "$LAST" "$SNAP" | zstd -T0 -3 |   ssh backup@nas 'zstd -d | btrfs receive /srv/backup'
ssh backup@nas 'btrfs subvolume list /srv/backup'

Ограничение команды через command=»…» в authorized_keys снижает риск: даже при утере ключа злоумышленник не получит полноценный shell. Проверьте, что на приёмнике есть место и что каталог смонтирован. Разрывы соединения обрывают поток, поэтому для больших объёмов лучше запускать передачу в tmux или systemd-юните с повторной попыткой.

Проверка и восстановление

Бэкап считается рабочим только после проверки. Сравните список файлов и выборочно прочитайте данные. Для восстановления достаточно создать снапшот из принятого subvolume или скопировать файлы.

btrfs subvolume snapshot /mnt/backup/2026-11-07 /mnt/restore/home
diff -r /home/Documents /mnt/restore/home/Documents | head
btrfs filesystem du -s /mnt/backup/* | tail -5
btrfs scrub start -B /mnt/backup

Scrub проверяет контрольные суммы и может выявить повреждение на приёмнике. Для важных данных держите вторую копию на другом носителе: send/receive защищает от логических ошибок и отказа диска, но не от пожара в комнате. Восстановление на другой компьютер стоит протестировать заранее.

Ограничения

Поток send/receive не заменяет файловый бэкап для других файловых систем и не переносит настройки монтирования. Он также не сжимает поток сам по себе: сжатие делает внешний инструмент вроде zstd. Нельзя принимать поток на XFS или ext4 — приёмник обязан быть Btrfs.

Ещё одна тонкость: инкремент опирается на родителя, а не на «любой похожий» снапшот. Переименование или удаление родителя ломает цепочку. Ведите журнал снапшотов и проверяйте его при каждой ротации. Для больших массивов полезно считать время передачи: если скрипт перешёл к полной отправке, проверьте цепочку снапшотов.

Чек-лист

  • Источник и приёмник — Btrfs, места достаточно.
  • Снапшоты создаются только для чтения.
  • Родительский снапшот есть на обеих сторонах.
  • Скрипт обновляет состояние только после успеха.
  • Ключ SSH ограничен командой receive.
  • Восстановление и scrub проверены на практике.

Итог

Btrfs send/receive даёт предсказуемый инкрементальный бэкап без лишних пакетов: снапшот, поток, приёмник. Секрет надёжности — дисциплина цепочки: не удалять родителя, фиксировать состояние после успешной передачи и регулярно проверять восстановление. Добавьте второй носитель и scrub, и копия перестанет быть формальностью.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте