![将块设备挂载为常规文件](https://linux22.com/image/165820/%E5%B0%86%E5%9D%97%E8%AE%BE%E5%A4%87%E6%8C%82%E8%BD%BD%E4%B8%BA%E5%B8%B8%E8%A7%84%E6%96%87%E4%BB%B6.png)
前言
假设我在机器 A 上有一个 1TB 的加密分区,其中包含十几个用户的主目录,我们称这个分区为sda2
。我想每天备份远程计算机 B 上的该分区。为了保持安全和简单,B 上的备份必须是 的精确映像副本sda2
。
sda2
我知道我可以使用命令创建本地映像dd
,甚至可以通过以下方式将其传送到 B ssh
:
$ dd if=/dev/sda2 | ssh B dd of=/backups/A.sda2.image
这种方法的问题在于分区的大小。 1TB 的数据不容易通过网络,这限制了备份操作的频率——实际上少于每月一次。此时就需要一个增量备份工具。
rsync
在我看来,就是解决之前困难的办法。但是,当我尝试测试它时,我失败了,因为rsync
将其/dev/sda2
视为特殊文件和命令:
$ rsync /dev/sda2 B:/backups/A.sda2.image
没有做我想做的事。
问题
有没有办法欺骗rsync
处理/dev/sda2
常规文件?
笔记
我不是问是否有一个rsync
选项可以做到这一点(如果有这样一个选项那就太好了,但这只是故事的一半)我想知道是否有类似命令mount
或系统调用之类的东西可以允许例如,我创建一个/mnt/sda2.live_image
包含 的原始内容的常规文件/dev/sda2
,以便其他应用程序可以通过 直接读取或sda2
写入sda2.live_image
。
任何帮助深表感谢。
答案1
您可以修补直通_fhlibfuse 演示文件系统如下:
diff --git a/example/passthrough_fh.c b/example/passthrough_fh.c
index 13eb41e..146cb03 100644
--- a/example/passthrough_fh.c
+++ b/example/passthrough_fh.c
@@ -72,6 +72,21 @@ static void *xmp_init(struct fuse_conn_info *conn,
return NULL;
}
+
+static void b2r(int devfd, struct stat *stbuf)
+{
+ off_t disk_size;
+
+ disk_size = lseek(devfd, 0, SEEK_END);
+ if (disk_size == -1)
+ return;
+
+ stbuf->st_size = disk_size;
+ stbuf->st_blocks = disk_size / stbuf->st_blksize;
+ stbuf->st_mode &= ~S_IFBLK;
+ stbuf->st_mode |= S_IFREG;
+}
+
static int xmp_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{
@@ -85,6 +100,16 @@ static int xmp_getattr(const char *path, struct stat *stbuf,
res = lstat(path, stbuf);
if (res == -1)
return -errno;
+ if (S_ISBLK(stbuf->st_mode)) {
+ int fd;
+ if (fi)
+ fd = fi->fh;
+ else
+ fd = open(path, O_RDONLY);
+ b2r(fd, stbuf);
+ if (!fi)
+ close(fd);
+ }
return 0;
}
如果将其安装为 root,它将向您提供文件系统的镜像,其中块设备显示为常规文件。仅传递-omodules=subdir,subdir=/dev
到镜像 /dev。
(我在我的双启动 Mac/Linux 机器上使用此补丁的一个变体,以便能够将我的 Linux 安装作为 OS X 中的 Xhyve VM 启动,因为 Xhyve 拒绝使用块设备。)
答案2
正如评论中所解释的,基于块设备的备份通常是一个错误的想法。
在非加密设备上,通常会使用以下步骤来完成此操作:
- 用零 (
dd if=/dev/zero of=<mountpoint>/tmp_zero_file bs=1M
) 填充空白空间,以便以更好的比率压缩可用空间。 - 然后
dd if=<your block device> |gzip -9 | ssh backup_host "cat > backup.gz"
- 然后
rm <mountpoint>/tmp_zero_file
。
这里的问题是,由于您的磁盘已加密,因此将 0 写入文件惯于由于加密层的原因,导致块归零。
对于您的用例,我强烈建议使用表里不一这是一个基于rsync的备份工具,实现加密和增量备份。
答案3
只要你查看整个分区,你就必须整个阅读才能发现发生了什么变化。事实上你必须阅读新版本和旧版本才能找到变化,所以你最好直接把整个东西复制过来。使用千兆位以太网和良好的磁盘,您可以获得 100MB/s,因此您的 TB 将需要 10000 秒或大约 3 小时,因此每晚备份是可行的。 OTOH,如果目标是 SSD,你会很快磨损它。
注意,你做的不是备份而是镜像。如果用户在一次镜像发生后才发现错误删除文件,这并不能真正帮助他们。