# 共享, 拷贝和存档

数据的安全和它的受控共享有如下几个方面。

- 存档文件的建立
- 远程存储访问
- 复制
- 跟踪修改历史
- 促进数据共享
- 防止未经授权的文件访问
- 检测未经授权的文件修改

这些可以通过使用工具集来实现。

- 存档和压缩工具
- 复制和同步工具
- 网络文件系统
- 移动存储媒介
- 安全 shell
- 认证体系
- 版本控制系统工具
- 哈希算法和加密工具

## 存档和压缩工具

| 软件包        | 扩展名   | 命令                     | 描述                                                                          |
|------------|-------|------------------------|-----------------------------------------------------------------------------|
| tar        | .tar  | tar(1)                 | 标准的归档工具（默认）                                                                 |
| cpio       | .cpio | cpio(1)                | Unix System V 风格的归档器，与 find(1) 一起使用                                         |
| binutils   | .ar   | ar(1)                  | 创建静态库的归档工具                                                                  |
| fastjar    | .jar  | fastjar(1)             | Java 归档工具（类似 zip）                                                           |
| pax        | .pax  | pax(1)                 | 新的 POSIX 归档工具，介于 tar 和 cpio 之间                                              |
| gzip       | .gz   | gzip(1), zcat(1), …    | GNU LZ77 压缩工具（默认）                                                           |
| bzip2      | .bz2  | bzip2(1), bzcat(1), …  | Burrows-Wheeler block-sorting 压缩工具有着比 gzip(1) 更高的压缩率 (跟 gzip 有着相似的语法但速度比它慢) |
| lzma       | .lzma | lzma(1)                | LZMA 压缩工具有着比 gzip(1) 更高的压缩率（不推荐)                                            |
| xz-utils   | .xz   | xz(1), xzdec(1), …     | XZ 压缩工具有着比 bzip2(1) 更高的压缩率（压缩速度慢于 gzip 但是比 bzip2 快; LZMA 压缩工具的替代品)          |
| zstd       | .zstd | zstd(1), zstdcat(1), … | Zstandard 快速无损压缩工具                                                          |
| p7zip      | .7z   | 7zr(1), p7zip(1)       | 有着更高压缩率的 7-zip 文件归档器（LZMA 压缩）                                               |
| p7zip-full | .7z   | 7z(1), 7za(1)          | 有着更高压缩率的 7-Zip 文件归档器（LZMA 压缩和其他）                                            |
| lzop       | .lzo  | lzop(1)                | LZO 压缩工具有着比 gzip(1) 更高的压缩和解压缩速度 (跟 gzip 有着相似的语法但压缩率比它低)                     |
| zip        | .zip  | zip(1)                 | InfoZip：DOS 归档器和压缩工具                                                        |
| unzip      | .zip  | unzip(1)               | InfoZIP：DOS 解档器和解压缩工具                                                       |

deepin也提供图形化的归档管理器，在系统中预装

::: warning 警告
除非你知道将会发生什么，否则不要设置 "$TAPE" 变量。它会改变 tar(1) 的行为
:::


::: tip

- gzipped tar(1) 归档器用于扩展名是 ".tgz" 或者 ".tar.gz" 的文件。
- xz-compressed tar(1) 归档器用于扩展名是 ".txz" 或者 ".tar.xz" 的文件。
- FOSS 工具，例如 tar(1)，中的主流压缩方法已经按如下所示的迁移: gzip → bzip2 → xz
- cp(1),scp(1) 和 tar(1) 工具可能并不适用于一些特殊的文件。cpio(1) 工具的适用范围是最广的。
- cpio(1) 是被设计为与 find(1) 和其它命令一起使用，适合于创建备份脚本的场景，因此，脚本的文件选择部分能够被独立测试。
- Libreoffice 数据文件的内部结构是 ".jar" 文件，它也可以使用 unzip 工具来打开。
- 事实上跨平台支持最好的存档工具是 zip。按照“zip -rX”的方式调用可以获得最大的兼容性。如果最大文件大小需要纳入考虑范围，请同时配合“-s”选项使用。
:::

## 复制和同步工具

| 软件包            | 工具     | 功能                         |
|----------------|--------|----------------------------|
| coreutils      | GNU cp | 复制本地文件和目录("-a" 参数实现递归）     |
| openssh-client | scp    | 复制远端文件和目录（客户端，"-r" 参数实现递归) |
| openssh-server | sshd   | 复制远端文件和目录（远程服务器）           |
| rsync          |        | 单向远程同步和备份                  |
| unison         |        | 双向远程同步和备份                  |

在复制文件的时候， rsync(8) 比其他工具提供了更多的特性。

- 差分传输算法只会发送源文件与已存在的目标文件之间的差异部分
- 快速检查算法 (默认) 会查找大小或者最后的修改时间有变化的文件
- "--exclude" 和 "--exclude-from" 选项类似于 tar(1)
- 在源目录中添加反斜杠的语法能够避免在目标文件中创建额外的目录级别

deepin的文件管理器也提供了webdav的支持，可以通过webdav协议访问远程文件，使用webdav同步文件也是一种不错的选择。
TODO：待补充

## 归档（压缩）语法

以下是用不同的工具压缩和解压缩整个 "./source" 目录中的内容。

GNU tar(1):

```Bash
tar -cvJf archive.tar.xz ./source
tar -xvJf archive.tar.xz
```

或者

```Bash
find ./source -xdev -print0 | tar -cvJf archive.tar.xz --null -F -
```

cpio(1):

```Bash
find ./source -xdev -print0 | cpio -ov --null > archive.cpio; xz archive.cpio
zcat archive.cpio.xz | cpio -i
```
其余工具使用见wiki

## 复制和同步语法

如下是用不同的工具复制整个 "./source" 目录中的内容。

- 本地复制: "./source" 目录 → "/dest" 目录
- 远程复制：本地主机上的 "./source" 目录 → "user@host.dom" 主机上的 "/dest" 目录

rsync(8):

```Bash
cd ./source; rsync -aHAXSv . /dest
cd ./source; rsync -aHAXSv . user@host.dom:/dest
```

你能够选择使用“源目录上的反斜杠”语法。

```Bash
rsync -aHAXSv ./source/ /dest
rsync -aHAXSv ./source/ user@host.dom:/dest
```

或者，如下所示。

```Bash
cd ./source; find . -print0 | rsync -aHAXSv0 --files-from=- . /dest
cd ./source; find . -print0 | rsync -aHAXSv0 --files-from=- . user@host.dom:/dest
```

GNU cp(1) 和 openSSH scp(1):

```Bash
cd ./source; cp -a . /dest
cd ./source; scp -pr . user@host.dom:/dest
```

GNU tar(1):

```Bash
(cd ./source && tar cf - . ) | (cd /dest && tar xvfp - )
(cd ./source && tar cf - . ) | ssh user@host.dom '(cd /dest && tar xvfp - )'
```

cpio(1):

```Bash
cd ./source; find . -print0 | cpio -pvdm --null --sparse /dest
```

你能够在所有包含 "`.`" 的例子里用 "`foo`" 替代 "`.`"，这样就可以从 "`./source/foo`" 目录复制文件到 "`/dest/foo`" 目录。

在所有包含 "`.`" 的列子里，你能够使用绝对路径 "`/path/to/source/foo`" 来代替 "`.`"，这样可以去掉 "`cd ./source`;". 如下所示，这些文件会根据工具的不同，拷贝到不同的位置。

- "/dest/foo": rsync(8), GNU cp(1), 和 scp(1)
- "/dest/path/to/source/foo": GNU tar(1), 和 cpio(1)

::: tip
rsync(8) 和 GNU cp(1) 可以用 "-u" 选项来忽略接受端上更新的文件。
:::

## 查找文件的语法

find(1) 被用作从归档中筛选文件也被用作拷贝命令 (参见第 10.1.3 节 “归档语法”和第 10.1.4 节 “复制语法”) 或者用于 xargs(1) (参见第 9.4.9 节 “使用文件循环来重复一个命令”)。通过 find 的命令行参数能够使其功能得到加强。

以下是 find(1)基本语法的总结。

- find 条件参数的运算规则是从左到右。
- 一旦输出是确定的，那么运算就会停止。
- “逻辑 OR" （由条件之间的 "-o" 参数指定的）优先级低于 "逻辑 AND" （由 "-a" 参数指定或者条件之间没有任何参数）。
- ”逻辑 NOT" (由条件前面的 "!" 指定) 优先级高于 “逻辑 AND”。
- "-prune" 总是返回逻辑 TRUE 并且如果这个目录是存在的，将会搜索除这个目录以外的文件。
- "-name" 选项匹配带有 shell 通配符 (参见第 1.5.6 节 “Shell 通配符”) 的文件名但也匹配带有类似 "*" 和 "?" 元字符的 ."。(新的 POSIX 特性)
- "-regex" 匹配整个文件路径，默认采用 emacs 风格的 BRE (参见第 1.6.2 节 “正则表达式”)。
- "-size" 根据文件大小来匹配 (值前面带有 "+" 号匹配更大的文件，值前面带有 "-" 号匹配更小的文件)
- "-newer" 参数匹配比参数名中指定的文件还要新的文件。
- "-print0" 参数总是返回逻辑 TRUE 并将完整文件名 (null terminated) 打印到标准输出设备上。

如下是 find(1) 语法格式。

```bash
find /path/to \
    -xdev -regextype posix-extended \
    -type f -regex ".*\.cpio|.*~" -prune -o \
    -type d -regex ".*/\.git" -prune -o \
    -type f -size +99M -prune -o \
    -type f -newer /path/to/timestamp -print0
```

这些命令会执行如下动作。

- 查找 "/path/to" 下的所有文件
- 限定全局查找的文件系统并且使用的是 ERE (参见第 1.6.2 节 “正则表达式”)
- 通过停止处理的方式来排除匹配 ".*\.cpio" 或 ".*~" 正则表达式的文件
- 通过停止处理的方式来排除匹配 ".*/\.git" 正则表达式的目录
- 通过停止处理的方式来排除比 99MB (1048576字节单元) 更大的文件
- 显示文件名，满足以上搜索条件并且比 "/path/to/timestamp" 新的文件

请留心以上例子中的 "-prune -o" 排除文件的习惯用法。

## 归档媒体

数据无价，所以你应该把它们存储在安全的地方。当你在寻找存储设备时，你应该注意它们的局限性。对于小型的个人数据备份，我使用品牌公司的 CD-R 和 DVD-R 然后把它放在阴凉、干燥、清洁的地方。(专业的一般使用磁带存档介质)

网上（主要是来源于供应商信息）可以查看存储介质的最大使用寿命。

- 大于100年：用墨水的无酸纸
- 100年：光盘存储（CD/DVD，CD/DVD-R）
- 30年：磁带存储（磁带，软盘)
- 20年：相变光盘存储（CD-RW）

这不包括由于人为导致的机械故障等等。

网上（主要来源于供应商信息）可以查看存储介质的最大的写次数。

- 大于250,000次：硬盘驱动器
- 大于10,000次：闪存
- 1,000次：CD/DVD-RW
- 1次：CD/DVD-R，纸

个人建议如果可行的话使用磁带或者光盘保存你的数据（比如和家人的照片）不要使用u盘或者闪存保存长期不使用的冷数据。
你可以使用第三方云服务来保存你的数据，比如Google Drive，Dropbox，OneDrive等等，如果你不放心数据安全的话可以加密你的数据之后再上传，或者自己搭建一个私有的云服务。

::: warning 注意
这里的存储寿命和写次数的数据不应该被用来决定任何用于关键数据的存储媒介，请翻阅制造商提供的特定产品的说明。
:::

::: tip
因为 CD/DVD-R 和 纸只能写一次，它们从根本上阻止了因为重写导致的数据意外丢失。这是优点！

如果你需要更快更频繁的进行大数据备份，那么通过高速网络连接的远端主机上的硬盘来实现备份，可能是唯一可行的方法。

如果你在使用一个可重复写入的介质作为你的备份介质，使用支持只读快照的 btrfs 或 zfs 文件系统，也许是一个好注意。
:::

## 可移动存储设备

可移动存储设备可能是以下的任何一种。

- USB 闪存盘
- 硬盘驱动器
- 光盘驱动器
- 数码相机
- 数字音乐播放器

它们可以通过以下的方式来进行连接。

- USB
- IEEE 1394 / FireWire（火线，现在很少见）
- PC 卡（常见于2010年前的笔记本电脑）
- 雷电（Thunderbolt，注意雷电3使用usb-c接口标准，但是不向下兼容usb协议）
- SATA3/eSATA （理论上支持热拔插的SATA硬盘也属于移动设备）

deepin 文件管理器会自动挂载可移动存储设备，你可以在文件管理器中看到它们。如果你想要在命令行中查看它们，你可以使用 mount(8) 命令。

- udisks2 包提供了守护进程和相关的实用程序来挂载和卸载这些设备。
- D-bus 创建事件来触发自动处理。
- PolicyKit 提供了所需的特权。

::: tip
umount(8) 在自动挂载设备的时候可能会带有 "uhelper=" 参数。
:::

::: tip
只有当这些可移动设备没有在 "/etc/fstab" 文件中列出时，桌面环境下才会自动挂载。
:::


现代桌面环境下的挂载点被选为 "/media/username/disk_label"，它可以被如下所示的来定制。

- FAT 格式的文件系统使用 mlabel(1) 命令
- ISO9660 文件系统使用带有 "-V" 选项的 genisoimage(1) 命令
- ext2/ext3/ext4 文件系统使用带有 "-L" 选项的 tune2fs(1) 命令

::: tip
挂载时可能需要提供编码选项（参见 第 8.1.3 节 “文件名编码”）。
:::

::: tip
在图形界面菜单上移除文件系统，可能会移除它的动态设备节点例如 "/dev/sdc"。如果你想要保留它的设备节点，你应该在命令行提示符上输入 umount(8) 命令来卸载它。
:::

## 选择用于数据分享的文件系统

在你的文件系统中，你应该选择一个用于数据分享的文件系统。这个文件系统应该支持以下的特性。

1. 你应该能够在不同的操作系统上访问它。
2. 不会存在文件过大导致的无法写入的问题。

下面是一些可供选择的文件系统。
| 文件系统名   | 典型使用场景                                                                                         |
|---------|------------------------------------------------------------------------------------------------|
| FAT12   | 软盘（<32MiB）上跨平台的数据分享                                                                            |
| FAT16   | 在小硬盘(<2GiB)上的跨平台的数据分享                                                                          |
| FAT32   | 在大硬盘（<8TiB，被 MS Windows95 OSR2 以上的操作系统所支持) 上的跨平台的数据分享                                          |
| exFAT   | 在大硬盘类设备上跨平台共享数据（<512TiB，被 WindowsXP, Mac OS X Snow Leopard 10.6.5 和 Linux 内核 5.4 版本以上的操作系统所支持) |
| NTFS    | 在大硬盘类设备上的跨平台共享数据 (在 MS Windows NT 和后续版本原生支持；在 Linux 上，通过使用 FUSE 的 NTFS-3G 支持。)                 |
| ISO9660 | 在 CD-R 和 DVD+/-R 上的跨平台的静态数据分享                                                                  |
| UDF     | CD-R 和 DVD+/-R (新)上的增量数据写入                                                                     |
| MINIX   | 软盘上磁盘空间高利用率的 unix 文件数据存储                                                                       |
| ext2    | 在装有老旧 linux 系统的硬盘上的数据分享                                                                        |
| ext3    | 在装有老旧 linux 系统的硬盘上的数据分享                                                                        |
| ext4    | 在装有较新的 linux 系统的硬盘上的数据分享                                                                       |
| btrfs   | 使用只读快照在装有较新的 Linux 系统的硬盘上共享数据                                                                  |

所以建议对于移动设备，你应该使用 exFAT 或者 FAT32。对于 CD/DVD，你应该使用 UDF。

FAT 文件系统被绝大多数的现代操作系统支持，它对于通过可移动硬盘进行的数据交换是非常有用的。

当格式化像装有 FAT 文件系统的跨平台数据共享的可移动设备时，以下应该是保险的选择。

- 用 fdisk(8)，cfdisk(8) 或者 parted(8) 命令（参见第 9.6.2 节 “硬盘分区配置”）把它们格式化为单个的主分区并对把它做如下标记。
  - 标记小于 2GB 的 FAT 设备为 字符"6"。
  - 标记更大的 FAT32 设备为字符 "c"。

- 如下所示是用 mkfs.vfat(8) 命令格式化主分区的。
  - 它的设备名字，例如 "/dev/sda1" 用于 FAT16 设备
  - 明确的选项和它的设备名，例如 "-F 32 /dev/sda1" 用于 FAT32 设备

当使用 FAT 或 ISO9660 文件系统分享数据时，如下是需要注意的安全事项。

- tar(1)，或cpio(1)命令压缩文件，目地是为了保留文件名，符号链接，原始的文件权限和文件所有者信息。
- 用 split(1) 命令把压缩文件分解成若干小于 2GiB的小文件，使其免受文件大小限制。
- 加密压缩文件保护其内容免受未经授权的访问。

::: warning 注意
因为 FAT 文件系统的设计，最大的文件大小为 (2^32 - 1) bytes = (4GiB -1 byte)。对于一些老旧的 32 位系统上的应用程序而言，最大的文件大小甚至更小(2^31 -1) bytes = (2GiB -1 byte)。Debian 没有遇到后者的问题。
:::

::: warning 注意
微软系统本身并不建议在超过 200MB 的分区或者驱动器上使用 FAT。他们的 " [Overview of FAT, HPFS, and NTFS File Systems](http://support.microsoft.com/kb/100108/) 这篇文章突出显示了微软系统的缺点，例如低效的磁盘空间利用。当然了，我们在 Linux 系统上还是应该使用 ext4 文件系统。
:::
::: tip
有关文件系统和访问文件系统的更多信息，请参考 "Filesystems HOWTO"。
:::

::: 网络上的数据分享

当使用网络来分享数据的时候，你应该使用通用的服务。这里有一些提示。
| 网络服务                      | 典型使用场景描述                                                                                                                                   |
|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| SMB/CIFS 用 Samba 挂载网络文件系统 | 通过 “Microsoft Windows 网络” 分享文件，参见 smb.conf(5) 和 官方 Samba 3.x.x 指导和参考手册（The Official Samba 3.x.x HOWTO and Reference Guide） 或 samba-doc 软件包 |
| NFS 用 Linux 内核挂载网络文件系统    | 通过 “Unix/Linux 网络" 分享文件，参见 exports(5) 和 Linux NFS-HOWTO                                                                                    |
| HTTP 服务                   | 在 web 服务器/客户端之间分享文件                                                                                                                        |
| HTTPS 服务                  | 在有加密的安全套接层 (SSL) 或者安全传输层 (TLS) 的网络服务器/客户端中分享文件                                                                                             |
| FTP 服务                    | 在 FTP 服务器/客户端之间分享文件                                                                                                                        |

尽管对于文件分享来说，通过网络挂载文件系统和传输文件是相当方便的，但这可能是不安全的。它们的网络连接必须通过如下所示的加强安全性。

- 用 SSL/TLS 加密
- 建立 SSH 通道
- 建立 VPN 通道
- 网络之间需要有安全的防火墙

参见 第 6.5 节 “其它网络应用服务” 和 第 6.6 节 “其它网络应用客户端”。
