Hatred's Log Place

DON'T PANIC!

May 13, 2010 - 6 minute read - linux

Резервное копирование при помощи rsync+ssh

Статей на эту тему много, к примеру:

Но нигде не нашел внятного объяснения как сохранять права доступа, группу и владельца, особенно, если удаленный сервер (backup-сервер) работает не от пользователя root.

В общем, постановка задачи:

  • инкрементный бекап
  • клиент-сервер
  • сохранять права доступа, владельца и группу
  • сохранять только указанные директории, представлять возможность исключения по паттерну, делать исключения в исключениях :)
  • выполнение каких-то операций пред выполнением резервирования

Настройка backup-сервера

Тут все достаточно просто, должны быть установлены пакеты openssh, rsync и их зависимости, openssh должен быть настроен и запущен.

Далее, создаем пользователя под которым будут храниться резервные копии, пусть это будет backup:

adduser backup

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

После чего, в его домашнем каталоге создаем подкаталоги lock и files:

  mkdir lock file

Затем создаем там же, в домашнем каталоге, файл rsyncd.conf с примерно таким содержимым:

# малость системной информации, подробнее 'man rsyncd.conf'
use chroot = no
max connections = 4
syslog facility = local5
pid file = /home/backup/lock/rsyncd.pid
lock file = /home/backup/lock/rsyncd.lock

[backup]
    comment = Backup area
    # хранить информацию о правах, владельце и группе в цифровом виде, если не нужно - поставьте no
    numeric ids = yes
    # эта опция позволяет хранить информацию о правах, владельце, группе в xattr, об этом далее
    fake super = yes
    # путь к корню, где будут храниться копии
    path = /home/backup/files
    # по умолчанию, все модули - read only, нам же нужно писать
    read only = no

Комментарии по тексту, думаю остальное избыточно.

Теперь ремарка… об этих самых xattr: Я столкнулся с тем, что при попытке записи, выдавалось сообщение об ошибке, и эти самые атрибуты не писались, гугл ответа не дал. Поставил пакет, зовется attr, который нужен для управления расширенными атрибутами файлов. Вдумчивое чтение man 5 attr дало следующее:

Currently, support for extended attributes is implemented on Linux by the ext2, ext3, ext4, XFS, JFS and reiserfs filesystems.

А, как следствие, вдумчивое чтение ‘man mount’ дало информацию о параметре монтирования user_xattr. У меня файловая система ext4, там этот атрибут по-умолчанию выключен, для сохранения информации о владельце/группе нужно его включить. Поэтому в /etc/fstab для нужной файловой системы после defaults добавил user_xattr, получилось примерно следующее:

  UUID=780ae01a-6fe2-416f-baa2-0d700cd9574f /home ext4 defaults,user_xattr 0 1

По сути, это все, что относится к серверной настройке, после потребуется только создания своего индивидуального подкаталога для каждого резервируемого хоста внутри ‘files’, я рекомендую создавать эти каталоги по имени хоста (вывода команды hostname). Пока создадим там каталог host1

Резервируемый хост

Тут нужно набросать скриптик и несколько конфигурационных файлов прописать его в cron для регулярного выполнения:

  • backup.sh - сам скрипт, понимает 3 аргумента:
    • backup - выполняет резервирование
    • list - показывает содержимое бекапа на сервере
    • restore <что> <куда> - восстанавливает данные из резервной копии
  • backup.conf - конфиг, что бы можно было оперативно размножить по разным хостам
  • backup.list - список файлов и директорий подлежащих резервированию
  • backup.exclude - список паттернов для исключения из резервирования (man rsync)
  • backup.include - писок исключений (отменяет некоторые паттерны в exclude, смотреть man rsync)
  • backup_cron - небольщой скрипт для выполнения планировщиком, я его положил в /etc/cron.hourly/, добавив префик zz_, что бы выполнялся последним.
  • hook.d/ - директория со скриптами, которые выполняется перед выполнением резервирования

Итак, сами скрипты.

  • backup.sh

    #!/bin/bash
    
    #
    ### Скрипт для инкрементного бекапа при помощи rsync+ssh
    #   с сохранением прав/владельца файла в расширенных
    #   атрибутов (требуется монтирование файловой системы на
    #   которую будет производится резервирование с опцией user_xattr)
    #
    # Version: 20100512.1
    #
    # «THE BEER-WARE LICENSE» (Revision 42):
    # hatred@inbox.ru wrote this file. As long as you retain
    # this notice you can do whatever you want with this stuff.
    # If we meet some day, and you think this stuff is worth it,
    # you can buy me a beer in return. Alexander 'hatred' Drozdoff 
    #
    
    source backup.conf
    
    [ -z "$host" ] && host=`hostname`
    
    exclude=backup.exclude
    include=backup.include
    backups=backup.list
    
    DAY=$(env LANG=C date +"%F_%H")
    
    do_hooks()
    {
        for pkg in hook.d/*
        do
            [ -x $pkg ] && ./$pkg
        done
    }
    
    do_backup()
    {
        is_incr_exists=$(ssh $ssh_user@$host "stat files/$dest/incr/$DAY > /dev/null 2>&1 && echo yes || echo no")
        if [ "$is_incr_exists" == "yes" ]; then
            ssh $ssh_user@$host rm -rf files/$dest/incr/$DAY
        fi
    
        do_hooks
    
        rsync -av -R <br/>
            -e "ssh -l $ssh_user" <br/>
            --fake-super <br/>
            --delete <br/>
            --delete-excluded <br/>
            --inplace <br/>
            --backup <br/>
            --backup-dir=/$dest/incr/$DAY <br/>
            --exclude-from=$exclude <br/>
            --include-from=$include <br/>
            $(cat $backups) <br/>
            $host::backup/$dest/full/
    }
    
    do_list()
    {
        rsync -v -e "ssh -l $ssh_user" $host::backup/$dest/$1
    }
    
    do_restore()
    {
        rsync -av -e "ssh -l $ssh_user" --super --safe-links $host::backup/$dest/$1 $2
    }
    
    do_help()
    {
        cat << _EOF_
    Use: $0 <backup|list|restore> [SRC] [DEST]
    _EOF_
    }
    
    action=$1
    shift
    
    case $action in
        backup)
            do_backup
        ;;
        list)
            do_list $@
        ;;
        restore)
            do_restore $@
        ;;
        *)
            do_help
        ;;
    esac
    
  • backup.conf

    # пользователь на бекап сервере, под которым хранятся резервные копии (того что мы создавали)
    ssh_user=backup
    
    # IP или HOST backup-сервера
    host=backup.server
    
    # Имя поддиректории в files на backup-сервере для хранения данных конкретного хоста
    dest=host
    
  • backup.list, просто список директорий и файлов, главное, если хотите сохранять саму директорию, а не его содержимое, не ставьте в конце “/”, т.е. вместо “/etc/” пишите “/etc”. примерное содержимое:

    /etc
    /home
    /root
    /var/backup
    
  • backup.exclude, список паттернов (man rsync). Обратите внимание, испключается последний элемент, т.е. /var/cache/*/* сохранит директории/файлы в /var/cache/, но исключит их содержимое . примерный список

    *~
    *.back
    /sys
    /dev
    /tmp
    /proc
    
  • backup.include, у меня пустой, позволяет делать отдельные исключения к exclude, т.е. для примера выше, если вписать /proc/cpuinfo, то cpuinfo будет сохраняться.

  • backup_cron, правится под ваши нужды, у меня примерно такой:

    #!/bin/bash
    
    cd /home/backup/backup/
    ./backup.sh backup > log/backup-$(date +%H).log 2>&1
    

    Куда его помещать, я уже выше писал, можно и просто crontab -e от root и прописать там в нужно время

Все, осталось под пользователем root создать ssh-ключи и передать их на backup-сервер:

ssh-keygen # (тут главное не ставьте парольную фразу, или заводите ssh-agent, но это другая история)
ssh-copy-id -i ~/.ssh/id_rsa backup@backup.server # спросит пароль пользователя backup, передаст ключ

По сути всё. Что в результате имеем: на сервере в каталоге host1/full хранится полная копия всех файлов на момент последнего запуска скрипта, передаются только измененные файлы, в каталоге host1/incr/YYYY-MM-DD_HH хранится копия перезаписываемого файла (т.е. если файл изменился, перед тем как он запишется в full, он оттуда сохраняется в incr/YYYY-MM-DD_HH, реализуя таким образом схему инкрементного бекапа).

Восстанавливать примерно так:

mkdir restore
./backup.sh restore full/ restore/
./backup.sh restore incr/2010-05-10_14/ restore/

Восстановит в т.ч. и атрибуты и владельца/группу, естественно восстановление нужно делать от пользователя root.

Скрипты я оформил, положил вместе со всеми остальными в git, получить можно:

git clone http://hatred.homelinux.net/git/scripts.git

в каталоге backup, там же посмотрите скрипт hook.d/pacman.sh, сохраняющем список пакетов перед резервированием.

Источники информации в системе

  • man rsync
  • man rsyncd.conf
  • man attr
  • man 5 attr
  • man mount

Tags: backup linux rsync

Xorg 1.8 YouTube и HTML5

comments powered by Disqus