我使用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可用性的解决方案,对用户来说是透明的。
答案 0 :(得分:1)
如果在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"
答案 1 :(得分:0)
问题是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
参考文献: