Бекапы делать важно - пожалуйста делайте бекапы, иначе потеряете данные. Многие люди уже потеряли данные, а вы будьте умнее.
Мой скрипт:
# Start this script from the git folder of this script
# This script accept path to the partition to backup (mounted)
# Use this script NOT from the system you want to backup - boot from another system
if [ -z "$1" ]; then
echo "Missing path of the source (what to backup)"
exit 1
fi
BEFORE=$(df -h)
STARTED=$(date)
DATE=`date "+%Y-%m-%d"`
p=$(pwd)
cd $1
# Because rsync --exclude-from accepts only relative pathes, not absolute
rsync --archive --acls --xattrs --delete --progress --verbose --exclude-from=$p/exclude.txt --filter=':- .gitignore' --link-dest=$p/last --mkpath $1 $p/$DATE
ln --symbolic --force --no-dereference $DATE last
echo "Started at: " $STARTED
echo "Current time: " $(date)
echo "Before:
$BEFORE
Now:
"
df -h
cd -
# How to restore:
#
# rsync --archive --acls --xattrs --progress --verbose <from> <to>
# /etc/fstab: alter UUID
# grub install (if new SSD) https://wiki.gentoo.org/wiki/Grub:
# grub-install
# Note that if SSD is more than 2 GB - you cannot use MBR, only GPT with EFI partition (Thinkpag T430 supports UEFI boot)
# emerge-webrsync
# emerge --sync guru
# Documentation:
# https://jumpcloud.com/blog/how-to-backup-linux-system-rsync
# https://wiki.archlinux.org/title/rsync
Тут не просто копирование (с атрибутами - исполняемый файл или нет, чтение/запись) но и использование хардлинков с предыдущего бекапа - если файл не изменился - места в новом бекапе он не займёт - то есть в папке нового бекапа будут все файлы, но часть из них может быть хардлинками предыдущего бекапа. Хардлинки выглядят как обычные файлы. Это и имеется в виду под словом "инкрементально".
Из man:
--link-dest=DIR hardlink to files in DIR when unchanged
Для экономии места и скорости - мы не хотим бекапить кеш и прочие ненужные файлы, мой exclude.txt:
dev/*
proc/*
sys/*
run/*
# Если всё-же запустили на рабочей системе, раньше я так делал
var/db/repos/gentoo
var/db/repos/guru
var/cache/distfiles/
tmp/*
var/tmp
lost+found
mnt/*
home/vitaly/.npm/
home/vitaly/.cache/
home/vitaly/.zoom/
home/vitaly/.mozilla/firefox/*/storage
home/vitaly/.config/google-chrome/
home/vitaly/.config/chromium/
home/vitaly/.config/Microsoft/Microsoft Teams/
home/vitaly/.config/teams-for-linux/
home/vitaly/.config/Slack/
home/vitaly/.thumbnails/
home/vitaly/.cache/
home/vitaly/.local/share/TelegramDesktop/tdata/user_data/cache/
home/vitaly/.local/share/TelegramDesktop/tdata/user_data/media_cache/
home/vitaly/.local/share/Steam/
home/vitaly/.googleearth/Cache/
home/vitaly/.local/share/OMaps/
home/vitaly/.config/Audius/Cache/
home/vitaly/.config/YandexMusic/Cache/
home/vitaly/.config/vesktop/sessionData/Cache/
home/vitaly/.config/bilibili/Cache/
home/vitaly/.local/share/Trash/
home/vitaly/go/pkg/mod/cache/
home/vitaly/.cargo/registry/
home/vitaly/record/out/
home/vitaly/Desktop/unreal-5-4-4/
Также игнорируются файлы из .gitignore каждой папки.
Скрипт показывает df -h
до и после - чтобы увидеть сколько места занял бекап.
Бекапить надо с другой системы; ну или желательно - рабочая система ведь создаёт файлы для процессов, а их бекапить смысла нет.
Бекаплю на отдельный старый HDD отформатированный в BTRFS - чтобы использовать ZSTD сжатие.
sudo apt install btrfs-progs -y
# https://details.nl/install-and-use-btrfs-on-ubuntu-20-04-lts
sudo mkfs.btrfs /dev/sdX
# Partitions are not needed
sudo mount -o compress-force=zstd:15 /dev/sdX /mnt
# Max compression level is 15
# Дефолтное сжатие можно добавить в fstab
После бекапа можно увидеть как хорошо сжалось:
sudo apt install btrfs-compsize
sudo compsize /mnt
Пример вывода:
Processed 54036 files, 42027 regular extents (42028 refs), 27150 inline.
Type Perc Disk Usage Uncompressed Referenced
TOTAL 73% 211G 289G 289G
zstd 28% 42M 148M 148M
none 100% 174G 174G 174G
Главное тут Perc
- чем ниже этот процент тем лучше.
Для каждой папки с конфигами я использую git репозиторий - и вот такой подход для бекапа всей системы. Знаю есть много инструментов для бекапа, но у меня пока так просто - инкрементальный бекап через rsync в btrfs с максимальным сжатием.
Комментарии (23)
Lx6g1ZG1
19.07.2025 13:05В rsync можно ещё добавить --sparse к остальным параметрам, это должно ускорить копирование некоторых файлов, в которых есть нули, эта пустота не будет копироваться.
Возникает вопрос: зачем btrfs? Если не используется резервное копирование средствами этой фс - там вроде можно снимать снапшоты. Ну и вообщем, если бекап rsync'ом, то кроме etc и home больше ничего и не нужно, а если что-то ещё, то проще целиком снапшоты делать
zdanevich-vitaly Автор
19.07.2025 13:05У меня основной диск на ext4.
Lx6g1ZG1
19.07.2025 13:05Почему тогда на внешнем диске предпочитаете btrfs, из-за сжатия?
На мой взгляд лучше идентичные фс использовать (для таких вещей как бекапы) - меньше сюрпризов
Biga
19.07.2025 13:05Этак можно использовать любую тулзу для бекапов (например, backintime), просто отформатировать fs под сжатие, чтобы лучше влезало.
dphilipo
19.07.2025 13:05Фс со снапшотами для хранения бэкапов не нужна.
Для того, чтобы сделать инкрементный бэкап сначала из вчерашней директории в сегодняшнюю директорию сделайте так:cp -al yesterday_dir today_dir
Эта команда сделает дерево директорий где вместо файлов - жесткие сссылки.
После этого делайте в today_dir копирование rsync'ом с ключами -a --delete.
rsync заменит измененные файлы новыми версиями разорвав жесткие ссылки или удалит директории или жесткие ссылки на файлы если на источнике для бэкапа они были удалены.Таким образом в каждой директории будет храниться снапшот директории на время бэкапа и дубли файлов создаваться не будут.
lgorSL
19.07.2025 13:05Так rsync тоже так умеет, если ему указать директорию предыдущего снапшота. Он сам создаст жёсткие ссылки для неизменившихся файлов.
Зачем это делать через cp?
Hopenolis
19.07.2025 13:05Почему не restic?
У него нормальная реализация инкрементальных бекапов вместо костылей с линками, нормальное сжатие вместо костылей с btrfs.
Нормальный способ указать что папку не надо бекапить (файлы CACHEDIR.TAG).
sergeygals
19.07.2025 13:05Тот же вопрос:) после restic все это выглядит так себе, особенно когда захочется большего, шифрования там или дополнительного залива копии бекапа в облаков.
drlight17
19.07.2025 13:05Urbackup в image режиме - норм, можно оживить полностью убитую вместе с загрузчиком систему. Да и места занимает такой бэкап сравнительно меньше, чем в файловом режиме.
poige
19.07.2025 13:05хардлинки — это чтобы изменение 1 байта в гигабайтном файле обнулило весь профит, вместо того, чтобы использовать подход модификации снэпшотов на целевой btrfs, которая в таком случае перепишет только один блок? Вы там патетически просите пожалуйста бэкапы делать — вы пожалуйста прежде, чем писать на тему бэкапов, хотя бы изучите предмет.
zdanevich-vitaly Автор
19.07.2025 13:05У меня основная файловая система ext4 где нет снапшотов.
poige
19.07.2025 13:05Повторю ещё разок: «чтобы использовать подход модификации снэпшотов на целевой btrfs». Целевая btrfs aka backup target это не то, откуда делается backup, а куда.
firegurafiku
19.07.2025 13:05Похоже, что ваш скрипт сломается, если запустить его из каталога, в пути к которому есть пробелы — переменная
p
присваивается и всюду подставляется без кавычек.Не понимаю, по какому принципу вы выбираете, когда поставить кавычки, а когда нет — как по мне, подстановки переменных нужно квотировать тотально, а не выборочно. Также имеет смысл проверять все свои скрипты через ShellCheck.
edo1h
19.07.2025 13:05как по мне, подстановки переменных нужно квотировать тотально, а не выборочно
Бывают случаи, когда лишние кавычки вредят, например
OPTS="-l" OPTS2="" OPTS2="-l --sort=none" ls $OPTS ls $OPTS2 ls $OPTS3 ls "$OPTS" # работает ls "$OPTS2" # НЕ работает ls "$OPTS3" # НЕ работает
я безусловно ставлю в кавычки только те переменные, что содержат имена файлов, в остальных случаях думаю ожидает ли вызываемая программа получить значение переменной, содержащее пробелы, как один аргумент
firegurafiku
19.07.2025 13:05Если у вас честный баш без требований совместимости с POSIX-шеллом, в этой ситуации очень удобно использовать массивы. Ваш пример я бы написал примерно так:
declare -ra options=(-l --sort=none) ls "${options[@]}"
Можно и без
declare -ra
, это моя привычка везде явно ставитьdeclare
/local
и делать переменные ридонли, если это возможно.В целом же ситуации, когда нужна подстановка без кавычек и никак иначе, конечно же, встречаются. Имхо, каждую такую ситуацию следует рассматривать как особый случай, объяснить причину в комментарии и отключить для строки диагностику ShellCheck:
# It's not possible to pass arrays via environment. Falling back to a plain string. # shellcheck disable=SC2086 ls ${MYSCRIPT_LS_OPTIONS:-}
edo1h
19.07.2025 13:05я наоборот стараюсь избегать башизмов, с busybox ash мне нередко приходится иметь дело.
и вообще, если не хватает posix shell, это верный знак того, что пора взять «нормальный» язык программирования (которым баш всё равно не является).
firegurafiku
19.07.2025 13:05По правде говоря, в статье с заголовком про «бэкап при помощи rsync и Btrfs» ожидал увидеть совершенно другой сетап. Что-то вроде такого:
средствами Btrfs делаем ридонли-снапшоты интересующих сабвольюмов,
затем c этих снапшотов спокойно, не отрываясь от работы делаем rsync-ом хороший, консистентный бэкап на удалённый сервер (или несколько серверов — данные зафиксированы и не изменятся между проходами).
Тут rsync можно заменить на restic и будет вообще хорошо: дедупликация, сжатия, шифрование из коробки. Плюс нативная поддержка S3 и Backblaze (и многих других облачных провайдеров — посредством rclone).
c46fd3da
21 век на дворе, https://github.com/jimsalterjrs/sanoid/wiki/Syncoid наше все. =)
Через rsync я откатываю особо критичные вещи только с VPS для которых ZFS слишком тяжелая.
firegurafiku
Хотя Sanoid/Syncoid — довольно популярная тулза (сам тоже пользуюсь), справедливости ради, я бы предпочёл не запускать от рута что-то, написанное на перле или других скриптовых языках. Страшновато: Perl и его стандартная бибилиотека — это много кода, где что-то может пойти не так.