#云存储 #文件 #上传 #挂载点 #分割 #备份

bin+lib scfs

一个便捷的分割和连接文件系统

14 个版本 (7 个破坏性版本)

0.10.3 2023年12月25日
0.10.2 2023年11月1日
0.10.1 2023年10月3日
0.10.0 2023年7月10日
0.6.1 2019年10月21日

#209文件系统

Download history 4/week @ 2024-03-13 3/week @ 2024-03-27 5/week @ 2024-04-03 1/week @ 2024-05-15 2/week @ 2024-05-22

每月69 次下载

WTFPL 许可证

96KB
2K SLoC

SCFS – SplitCatFS

一个便捷的分割和连接文件系统。

动机

历史

在设置基于云的备份和归档解决方案时,我遇到了以下现象:许多小文件上传得相当快,并且 – 取决于实际的云存储提供商 – 高度并发,而大文件往往会减慢整个过程。解释很简单,许多云存储提供商不支持单个文件的并发或分块上传,有时甚至不支持恢复部分上传。您需要一次性上传,按顺序一个字节一个字节,要么全有,要么全无。

现在考虑一种情况,您上传一个巨大的文件,比如包含系统和配置的Raspberry Pi SD卡的镜像。我有一个这样的文件,大约有4GB大。现在,在备份我的系统时,这是最后一个要上传的文件。根据预计时间计算,这需要几个小时,所以我让它过夜。第二天早上我发现,在上传过程大约95%的时候,我的互联网连接突然中断了几秒钟,但足以让传输工具中断上传。临时文件从云存储中删除,所以我不得不重新从零开始。几个小时的上传时间浪费了。

我想到了一种方法来分割大文件,以便我可以更有效地上传它们,但最终得出结论,手动分割文件、上传它们并在本地删除它们不是一种非常可扩展的解决方案。

因此,我想出了一个特殊文件系统的想法。一个将大文件呈现为许多单独文件中的小片段的文件系统。实际上,这些片段都会指向同一个物理文件,只是有不同的偏移量。这样我就可以并行上传分块文件,而不会损失太多进度,即使上传过程中途中断。

SplitFS 就是这样诞生的。

如果我下载这样的分块文件部分,我需要在之后调用 cat * >file 以重新创建实际文件。这似乎与手动分割文件一样麻烦。这就是为什么我在开发SCFS时也考虑了 CatFS。CatFS将透明地连接分块文件,并将它们再次呈现为完整文件。

为什么 Rust?

我相对较新接触Rust语言,我认为,要想深入理解Rust,最好的方式是承担一个需要投入时间和对语言有一定了解的项目。

安装

SCFS可以通过Cargo轻松安装,通过crates.io

cargo install scfs

使用

Usage: scfs <COMMAND>

Commands:
  split  Create a splitting file system
  cat    Create a concatenating file system
  help   Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

SplitFS

Usage: scfs split [OPTIONS] <MIRROR> <MOUNTPOINT> [-- <FUSE_OPTIONS_EXTRA>...]

Arguments:
  <MIRROR>                 Defines the directory that will be mirrored
  <MOUNTPOINT>             Defines the mountpoint, where the mirror will be accessible
  [FUSE_OPTIONS_EXTRA]...  Additional options, which are passed down to FUSE

Options:
  -b, --blocksize <BLOCKSIZE>        Sets the desired blocksize [default: 2097152]
  -o, --fuse-options <FUSE_OPTIONS>  Additional options, which are passed down to FUSE
  -d, --daemon                       Run program in background
      --mkdir                        Create mountpoint directory if it does not exist already
  -h, --help                         Print help
  -V, --version                      Print version

要使用SplitFS挂载目录,请使用以下格式

scfs split <base directory> <mount point>

这可以通过使用专门的splitfs二进制文件来简化

splitfs <base directory> <mount point>

指定的挂载点目录将反映基础目录的内容,将每个常规文件替换为包含该文件枚举分块的目录作为单独的文件。

可以使用自定义的块大小来处理文件片段。例如,要使用1 MB块而不是默认的2 MB大小,您可以使用

splitfs --blocksize=1048576 <base directory> <mount point>

其中1048576等于1024 * 1024,即1兆字节。

您甚至可以利用Shell的计算能力,例如在Bash中

splitfs --blocksize=$((1024 * 1024)) <base directory> <mount point>

自v0.9.0起新增:现在也可以用符号量词来指定块大小。允许的量词有“K”,“M”,“G”和“T”,每个量词都乘以1024。所以,为了设置与上面示例相同的1 MB块大小,现在可以这样做

splitfs --blocksize=1M <base directory> <mount point>

实际上,您甚至可以将块大小设置为1字节,但请做好准备,因为元数据表会变得非常大,可能需要处理大量的开销,甚至可能导致系统冻结。

CatFS

Usage: scfs cat [OPTIONS] <MIRROR> <MOUNTPOINT> [-- <FUSE_OPTIONS_EXTRA>...]

Arguments:
  <MIRROR>                 Defines the directory that will be mirrored
  <MOUNTPOINT>             Defines the mountpoint, where the mirror will be accessible
  [FUSE_OPTIONS_EXTRA]...  Additional options, which are passed down to FUSE

Options:
  -o, --fuse-options <FUSE_OPTIONS>  Additional options, which are passed down to FUSE
  -d, --daemon                       Run program in background
      --mkdir                        Create mountpoint directory if it does not exist already
  -h, --help                         Print help
  -V, --version                      Print version

要使用CatFS挂载目录,请使用以下格式

scfs cat <base directory> <mount point>

这可以通过使用专门的catfs二进制文件来简化

catfs <base directory> <mount point>

请注意,基础目录必须是SplitFS生成的目录结构。否则,CatFS将拒绝挂载该目录。

指定的挂载点目录将反映基础目录的内容,将目录中的每个分块文件替换为单个文件。

额外的FUSE挂载选项

可以将额外的挂载选项传递给底层的FUSE库。

SCFS支持两种指定选项的方式,一种是使用“-o”选项,另一种是使用“--”分隔符后的额外参数。这与其他基于FUSE的文件系统如EncFS相一致。

这两个调用是等效的

scfs split -o nonempty mirror mountpoint
scfs split mirror mountpoint -- nonempty

当然,这些方法也适用于splitfscatfs二进制文件。

守护进程模式

最初,SCFS旨在在前景运行。如果想要在同一个终端中继续工作,这会显得有些麻烦。当然,您可以使用Shell的功能将进程发送到后台,但这样您就有一个可能会在用户关闭终端时意外被杀死的后台进程。此外,SCFS最初在外部卸载时不会干净地终止。

自v0.9.0起,SCFS原生支持守护进程模式,即程序将其工作目录更改为"/"/"/",然后将其自身作为真正的守护进程进程派生出来,独立于运行中的终端。

splitfs --daemon mirror mountpoint

请注意,在更改工作目录之前,会解析mirrormountpoint,因此它们仍然可以相对于当前工作目录给出。

要卸载,可以使用fusermount

fusermount -u mountpoint

限制

我认为这个项目已经不再是“原始原型”,我正在吃自己的狗粮,这意味着我正在将它们用于自己的备份策略,并基于个人需求创建功能。

然而,这可能无法满足典型用户的需求,如果没有反馈,我可能甚至不会考虑一些初始场景。

具体来说,这些是SCFS当前的限制

  • 它应该在所有基于UNIX的系统上工作,如Linux和一些MacOS版本,但不包括MacOS特定的文件属性。但肯定不在Windows上,因为这需要处理系统调用的特殊处理,我还没有时间处理。

  • 它只能与目录、常规文件和符号链接一起工作。其他文件类型(设备文件、管道等)将被静默忽略。

  • 基础目录将在新的挂载点上以只读方式挂载,SCFS期望在挂载期间基础目录不会被修改。

依赖项

~25–34MB
~557K SLoC