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

Мой скрипт:

# 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)


  1. c46fd3da
    19.07.2025 13:05

    21 век на дворе, https://github.com/jimsalterjrs/sanoid/wiki/Syncoid наше все. =)

    Через rsync я откатываю особо критичные вещи только с VPS для которых ZFS слишком тяжелая.


    1. firegurafiku
      19.07.2025 13:05

      Хотя Sanoid/Syncoid — довольно популярная тулза (сам тоже пользуюсь), справедливости ради, я бы предпочёл не запускать от рута что-то, написанное на перле или других скриптовых языках. Страшновато: Perl и его стандартная бибилиотека — это много кода, где что-то может пойти не так.


  1. Lx6g1ZG1
    19.07.2025 13:05

    В rsync можно ещё добавить --sparse к остальным параметрам, это должно ускорить копирование некоторых файлов, в которых есть нули, эта пустота не будет копироваться.

    Возникает вопрос: зачем btrfs? Если не используется резервное копирование средствами этой фс - там вроде можно снимать снапшоты. Ну и вообщем, если бекап rsync'ом, то кроме etc и home больше ничего и не нужно, а если что-то ещё, то проще целиком снапшоты делать


    1. zdanevich-vitaly Автор
      19.07.2025 13:05

      У меня основной диск на ext4.


      1. Lx6g1ZG1
        19.07.2025 13:05

        Почему тогда на внешнем диске предпочитаете btrfs, из-за сжатия?

        На мой взгляд лучше идентичные фс использовать (для таких вещей как бекапы) - меньше сюрпризов


        1. zdanevich-vitaly Автор
          19.07.2025 13:05

          Да, решил попробовать btrfs только из-за сжатия.


  1. Biga
    19.07.2025 13:05

    Этак можно использовать любую тулзу для бекапов (например, backintime), просто отформатировать fs под сжатие, чтобы лучше влезало.


  1. dphilipo
    19.07.2025 13:05

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

    cp -al yesterday_dir today_dir

    Эта команда сделает дерево директорий где вместо файлов - жесткие сссылки.
    После этого делайте в today_dir копирование rsync'ом с ключами -a --delete.
    rsync заменит измененные файлы новыми версиями разорвав жесткие ссылки или удалит директории или жесткие ссылки на файлы если на источнике для бэкапа они были удалены.

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


    1. lgorSL
      19.07.2025 13:05

      Так rsync тоже так умеет, если ему указать директорию предыдущего снапшота. Он сам создаст жёсткие ссылки для неизменившихся файлов.
      Зачем это делать через cp?


  1. Hopenolis
    19.07.2025 13:05

    Почему не restic?

    У него нормальная реализация инкрементальных бекапов вместо костылей с линками, нормальное сжатие вместо костылей с btrfs.

    Нормальный способ указать что папку не надо бекапить (файлы CACHEDIR.TAG).


    1. sergeygals
      19.07.2025 13:05

      Тот же вопрос:) после restic все это выглядит так себе, особенно когда захочется большего, шифрования там или дополнительного залива копии бекапа в облаков.


  1. drlight17
    19.07.2025 13:05

    Urbackup в image режиме - норм, можно оживить полностью убитую вместе с загрузчиком систему. Да и места занимает такой бэкап сравнительно меньше, чем в файловом режиме.


  1. poige
    19.07.2025 13:05

    хардлинки — это чтобы изменение 1 байта в гигабайтном файле обнулило весь профит, вместо того, чтобы использовать подход модификации снэпшотов на целевой btrfs, которая в таком случае перепишет только один блок? Вы там патетически просите пожалуйста бэкапы делать — вы пожалуйста прежде, чем писать на тему бэкапов, хотя бы изучите предмет.


    1. zdanevich-vitaly Автор
      19.07.2025 13:05

      У меня основная файловая система ext4 где нет снапшотов.


      1. poige
        19.07.2025 13:05

        Повторю ещё разок: «чтобы использовать подход модификации снэпшотов на целевой btrfs». Целевая btrfs aka backup target это не то, откуда делается backup, а куда.


      1. pol_pot
        19.07.2025 13:05

        Это легко лечится Ж) ext4 можно быстро сконвертить в btrfs.


        1. zdanevich-vitaly Автор
          19.07.2025 13:05

          Стоит? Минусы будут?


  1. ronden
    19.07.2025 13:05

    Использую borg. Просто работает. Танцев с бубном ненадо.


  1. firegurafiku
    19.07.2025 13:05

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

    Не понимаю, по какому принципу вы выбираете, когда поставить кавычки, а когда нет — как по мне, подстановки переменных нужно квотировать тотально, а не выборочно. Также имеет смысл проверять все свои скрипты через ShellCheck.


    1. 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" # НЕ работает
      

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


      1. 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:-}
        


        1. edo1h
          19.07.2025 13:05

          я наоборот стараюсь избегать башизмов, с busybox ash мне нередко приходится иметь дело.
          и вообще, если не хватает posix shell, это верный знак того, что пора взять «нормальный» язык программирования (которым баш всё равно не является).


  1. firegurafiku
    19.07.2025 13:05

    По правде говоря, в статье с заголовком про «бэкап при помощи rsync и Btrfs» ожидал увидеть совершенно другой сетап. Что-то вроде такого:

    • средствами Btrfs делаем ридонли-снапшоты интересующих сабвольюмов,

    • затем c этих снапшотов спокойно, не отрываясь от работы делаем rsync-ом хороший, консистентный бэкап на удалённый сервер (или несколько серверов — данные зафиксированы и не изменятся между проходами).

    Тут rsync можно заменить на restic и будет вообще хорошо: дедупликация, сжатия, шифрование из коробки. Плюс нативная поддержка S3 и Backblaze (и многих других облачных провайдеров — посредством rclone).