Сбой rsync многопользовательского каталога с монтированием предохранителя sshfs

Я использую rsync для периодической автоматической синхронизации домашней папки (пользователя root) на Linux-сервере, которым пользуются несколько человек. Услуга, которая нужна пользователям, — это возможность монтирования удаленных каталогов через sshfs. Однако, когда есть монтирование sshfs, rsync не дает следующие сообщения

rsync: readlink_stat("/home/???/???") failed: Permission denied (13)
IO error encountered -- skipping file deletion
...
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1183) [sender=3.1.1]

Из-за этой ошибки автоматическая синхронизация не работает должным образом, в частности, из-за пропуска удаления файла и ненулевого кода выхода. Синхронизация необходима только для файловой системы, в которой смонтирован home, поэтому желательно, чтобы монтирование sshfs игнорировалось. Параметр -x / --one-file-system rsync не решает эту проблему.

Эта проблема четко описана в https://www.agwa.name/blog/post/how_fuse_can_break_rsync_backups< /а> . Последующая статья (https://www.agwa.name/blog/post/easily_running_fuse_in_an_isolated_mount_namespace) предлагает решение, хотя и неприемлемое, потому что монтирования предохранителей видны только процессу, создавшему монтирование.

Я ищу решение, которое не влияет на удобство использования sshfs и прозрачно для пользователей.


person Mauricio Villegas    schedule 17.04.2017    source источник
comment
SO предназначен для вопросов по программированию, а не вопросов по использованию или настройке Linux. Попробуйте SuperUser.com или unix.stackexchange.com.   -  person Barmar    schedule 17.04.2017


Ответы (2)


Эта ошибка не появляется, если точки монтирования фьюзов исключены в команде rsync. Поскольку это автоматическая синхронизация, команду mount можно использовать для получения всех точек крепления предохранителей. Вывод команды mount может различаться в зависимости от системы, но в debian jessie sshfs монтирование отображается как USER@HOST:MOUNTED_DIR в /path/to/mount/point типа fuse.sshfs (rw,...). Простой способ автоматизировать исключение креплений предохранителей в bash+sed заключается в следующем.

SOURCE="/home/"

FUSEEXCLUDE=( $( mount |
  sed -rn "
    / type fuse/ {
      s|^[^ ]+ on ([^ ]+) type fuse.+|\1|;
      /^${SOURCE//\//\\\/}.+/ {
        s|^${SOURCE//\//\\\/}| --exclude |;
        p;
      }
    }" ) )

rsync $OPTIONS "${FUSEEXCLUDE[@]}" "$SOURCE" "$TARGET"
person Mauricio Villegas    schedule 17.04.2017
comment
Хорошее использование sed для поиска монтирования sshfs. Возможно ли, что некоторые из регулярных выражений немного искажены? s/^.+ on ([^.]+) type fuse.+/\1/ у меня сработало первое выражение. - person SimonSC; 06.07.2017
comment
@SimonSC, регулярное выражение не было искажено. Возможно, выходной формат вашей команды mount немного отличается, и поэтому он не работал. Обратите внимание, что в моей версии строка перед on и точка монтирования между on и type fuse не должны содержать пробелов. Фактически, отсутствие пробела в точке монтирования необходимо для правильного определения массива bash. - person Mauricio Villegas; 08.07.2017

Проблема в том, что FUSE запрещает доступ к статистике другим пользователям, включая root. Rsync требует доступа к статистике для всех указанных исходных файлов и каталогов. Но когда процесс rsync, принадлежащий другому пользователю, указывает точку монтирования FUSE, FUSE отказывает этому процессу в доступе к атрибутам точки монтирования, в результате чего rsync выдает указанную ошибку «отказано в доступе». Решение Mauricio Villega работает, говоря rsync пропускать точки монтирования FUSE, перечисленные командой mount. Вот еще одна версия решения Villega, в которой указывается белый список типов файловых систем с помощью команды findmnt. Я выбрал ext3 и ext4, но вы можете добавить другие типы по мере необходимости.

#!/bin/sh
# Which paths to rsync (note the lack of trailing slash tells rsync to preserve source path name at destination).
SOURCES=(
/home
)
# Which filesystem types are supported.
FSTYPES=(
ext3
ext4
)
# Rsync each source.
for SOURCE in ${SOURCES[@]}; do
  # Build exclusion list (array of "--exclude=PATH").
  excludedPaths=$(findmnt --invert --list --noheadings --output TARGET --types $(IFS=',';echo "${FSTYPES[*]}"))
  printf -v exclusionList -- "--exclude=%s " ${excludedPaths[@]}
  # Rsync.
  rsync --archive ${exclusionList[@]} --hard-links --delete --inplace --one-file-system ${SOURCE} /backup
done

Обратите внимание, что он создает список исключений внутри цикла, чтобы решить фундаментальную проблему этого решения. Эта проблема возникает из-за rsync из действующей системы, где пользователь может создавать новые точки монтирования FUSE во время работы rsync. Список исключений необходимо обновлять достаточно часто, чтобы включать новые точки монтирования FUSE. Вы можете разделить домашний каталог на каждое имя пользователя, изменив массив SOURCES, как показано ниже.

SOURCES=(
/home/user1
/home/user2
)

Если вы используете LVM, альтернативным решением является rsync из моментального снимка LVM. Моментальный снимок LVM обеспечивает простое (например, без точек монтирования FUSE) и фиксированное представление логического тома, с которым он связан. Недостатком является то, что вы должны зарезервировать место для действия копирования при записи моментального снимка LVM (COW). Крайне важно отказаться от моментального снимка LVM после того, как вы закончите с ним; в противном случае моментальный снимок LVM будет продолжать увеличиваться в размере по мере внесения изменений. Вот пример сценария, который использует моментальные снимки LVM. Обратите внимание, что нет необходимости создавать список исключений для rsync.

# Create and mount LVM snapshot.
lvcreate --extents 100%FREE --snapshot --name snapRoot /dev/vgSystem/lvRoot
mount -o ro /dev/mapper/snapRoot /root/mnt # Note that only root has access to this mount-point.
# Rsync each source.
for SOURCE in ${SOURCES[@]}; do
  rsync --archive --hard-links --delete --inplace --one-file-system /root/mnt/${SOURCE} /backup
done
# Discard LVM snapshot.
umount /root/mnt
lvremove vgSystem/snapRoot

Использованная литература:

"Как FUSE может нарушить резервное копирование Rsync"

person Aaron Arthurs    schedule 04.01.2019