簡體   English   中英

使用sshfs保險絲安裝的多用戶目錄的rsync失敗

[英]Failure of rsync of multi-user directory with sshfs fuse mount

我將rsync用於由幾個人使用的linux服務器中主文件夾(root用戶)的自動定期同步。 用戶需要的服務是可以通過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可用性並且對用戶透明的解決方案。

如果rsync命令中排除了保險絲安裝點,則不會出現此錯誤。 由於它是自動同步,因此可以使用mount命令獲取所有保險絲安裝點。 mount命令的輸出可能因系統而異,但是在debian jessie sshfs中,安裝路徑在/ path / to / mount / point類型fuse.sshfs(rw,...)上顯示為USER @ HOST:MOUNTED_DIR。 下面是一種自動排除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"

問題是FUSE拒絕對其他用戶(包括root)的統計信息訪問。 Rsync要求對指定的所有源文件和目錄具有統計信息訪問權限。 但是,當另一個用戶擁有的rsync進程統計FUSE掛載點時,FUSE拒絕該進程對掛載點屬性的訪問,從而導致rsync拋出“拒絕權限”錯誤。 Mauricio Villega的解決方案通過告訴rsync跳過mount命令列出的FUSE安裝點來工作。 這是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,用戶可以在其中運行rsync的同時創建新的FUSE掛載點。 排除列表需要經常更新,以包括新的FUSE掛載點。 您可以通過修改SOURCES數組,按每個用戶名進一步划分主目錄。

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

如果使用的是LVM,另一種解決方案是從LVM快照進行rsync。 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備份”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM