迁移数据

来自 Alpine Linux

我们比较了几种复制/迁移大量数据的方法。目的是保留所有文件权限和元数据,这需要在源文件系统和目标文件系统上都具有 root 访问权限。

我们包含了一些关于 BusyBox 实现中不可用的选项的信息,因为您可能会将数据复制到/从安装了其他 Unix 工具的系统,这些工具确实提供了这些选项。

警告: 以下任何方法都不会将引导管理器(ext/syslinux、grub 等)复制到新驱动器;您必须在那里显式安装它。


位复制方法

如果您的源数据占据整个分区(即,该分区上没有其他内容),并且您的目标分区大小相同或更大,并且您愿意让它使用与源相同的文件系统,那么一种选择是位复制整个源分区


从 LiveCD 启动并确保 /dev/sourcepart 和 /dev/targetpart 都没有被挂载。

示例

dd bs=10M if=/dev/sourcepart of=/dev/targetpart

这也将 sourcepart 上未占用的块复制到 targetpart。更优化的变体是使用 partimage,它仅复制 sourcepart 的已用部分。一个限制是当前(v0.6.9,发布于 2010 年 7 月,截至 2012 年 3 月)partimage 不支持 ext4 格式。

待办事项: 通常,目标分区将具有与源分区相同的分区类型(例如,Linux 0x83);但这是否绝对必要?


完成后,targetpart 上的文件系统可能占用的空间少于 targetpart 上的可用总空间。您可能需要使用 像 resize2fs 这样的工具来扩展分区。


更高级别的方法

我们将讨论的其他选项假设目标文件系统已格式化并挂载为 /target

如果您需要从正在运行的系统复制易失性数据,您可能需要从 lvm 快照复制,或者从单用户模式或 LiveCD 或其他启动介质进行复制,以便您的源数据在复制期间不被使用。如果您想从 /home 或类似位置复制,则无需采取此类预防措施。

如果您要复制完整的文件系统,您可能只想复制 /sys/proc 挂载点,而不是它们的当前内容。请记住复制 /boot/dev/tmp,最后两个可能需要特别注意。注意其他挂载点(例如 /mnt/media)和基于 RAM 的文件系统(例如 /run/lib/rc/init.d)。

待办事项: 前面的评论假设您知道自己在做什么,并且仅作为提醒。最好链接到更完整的解释。


注意: 现在,/dev 在某些系统上很棘手,因为它被 udev 隐藏了。这是一个可能的解决方案:

mkdir /tmp/dev mount --move /dev /tmp/dev 使用此页面其他地方的方法之一将 /dev 复制到 /mnt/sdb5 mount --move /tmp/dev /dev rmdir /tmp/dev


cp

根据您使用的系统以及您要复制的数据类型,您可能能够仅使用 cp 完成令人满意的本地复制。但是,有许多限制使其无法成为通用解决方案。

cp 的 Gnu 实现提供了以下选项(以及其他选项)

  • -a: 与 -RP -p/--preserve=mode,ownership,timestamps,links,context,xattr 相同
  • -v: 详细模式
  • -l: 创建硬链接而不是复制
  • -s: 创建符号链接而不是复制(源文件名必须是绝对路径)
  • --sparse=always
  • -u, --update: 除非文件的 mtime 较旧,否则不覆盖现有文件或符号链接
  • -x, --one-file-system: 跳过不同卷上的子目录

BusyBox 版本提供了除 --sparse-u-x 之外的所有 GNU 选项,并且可能缺少 --preservecontextxattr 选项。它将保留硬链接:如果 /source/A/source/B 是硬链接,则 /target/A/target/B 也将彼此成为硬链接(但不是与原始文件)。 BusyBox 的 cp 似乎会默默地忽略 -v 选项。

FreeBSD 实现提供了除 -s--sparse-u 之外的所有这些选项,以及从 links 开始的 --preserve 选项:特别是,它始终将硬链接复制为单独的文件。Mac 版本与 FreeBSD 版本有相同的限制,并且还缺少 -x。此外,在 Mac 版本上,-a 快捷方式不可用,您必须显式声明 -RPp

注意: 正如刚才解释的,其中一些实现会破坏硬链接。
警告: 避免使用小写 -r 选项。其行为在不同实现之间有所不同,并且可能与您对特殊文件或符号链接的期望不符。



tar

BusyBox 和其他实现识别的选项

  • -c: 创建新归档文件,记录现有权限和 mtime,符号所有者/组(可以指定 --numeric-owner),归档文件元素之间的硬链接
  • -x: 从归档文件中提取文件,使用当前所有者/组,除非 root 用户,否则减去当前 umask,除非 root 用户或 -p,否则提取硬链接时必须包含第一个
  • -t: 列出归档文件的内容
  • -f archive: 使用 -f - 表示标准输入/输出
注意: 在某些但不是所有实现中,当未提供 -f 时,归档文件默认为标准输入/输出。始终显式声明此项是最具可移植性的。
  • -O: 将文件提取到标准输出
  • -C dir: 更改到目录 dir,创建时此项对顺序敏感
  • -v: 详细模式
  • -z: 使用 gzip 压缩归档文件
  • -j: 使用 bzip2 压缩归档文件
  • -Z: 使用 compress 压缩归档文件
  • -h: 跟随符号链接,归档和提取它们指向的文件(类似于其他程序中的 -L
  • -m: 不提取文件的原始 mtime,保留为提取时间
  • -T file: 从 file 获取要提取或创建的名称,该文件还可以包含 “-C/etc” 行
  • --exclude=pattern: 排除指定的 glob pattern 模式
  • -X file: 排除在 file 中列出的 glob 模式
注意: 默认 globbing 规则:(i) 在任何 / 之后匹配,而不仅仅是在 ^ 处;(ii) 区分大小写;(iii) 通配符匹配 /

以下常用选项据称也受到 BusyBox 的支持(根据其源代码中的注释),但未在其 --help 中声明

  • -o, --no-same-owner: (BSD 不识别长选项) 以您自己身份提取(普通用户的默认设置)
  • -p, --same-permissions: (BSD 不识别此长选项) 完全按照权限提取,而不是减去当前 umask(通常是 root 用户的默认设置)
  • --no-same-permissions: 从提取的权限中减去 umask(普通用户的默认设置)
  • --numeric-owner: 使用数字创建用户/组
  • -k: 提取时不要替换现有文件
  • --overwrite: (不在 BSD 上)在提取时更积极地覆盖现有文件和目录元数据
    tar 的默认行为是首先删除现有文件(否则,它们的所有硬链接都将被修改)和符号链接。如果现有目录非空,则不会删除其现有内容;tar 将改为仅更新目录的元数据。--overwrite 改为跟随现有符号链接,并删除任何阻碍提取的内容,除非非空目录。(Gnu 的 --recursive-unlink 甚至会删除这些目录,可能会用文件或符号链接替换它们。)

GNU 选项(Mac 和 FreeBSD 也一样,除非另有说明)包括

  • --one-file-system: 创建归档文件时,停留在指定根目录所在的卷上,不要跨越挂载点
  • --null: -T 读取空字符结尾的名称,忽略 “-C/etc” 条目
  • -l, --check-links: (仅 BSD 用于 -c)在创建或提取时,如果并非所有硬链接都已处理,则打印消息
  • -S, --sparse: (不在 BSD 上)创建归档文件时,高效处理稀疏文件


一些 GNU tar 格式

  • 将来,它将默认为 -H posix/pax,这是 POSIX.1-2001 格式
  • v.1.13 - 当前版本(v1.26 发布于 2011 年 3 月,在 2012 年 3 月仍然是当前版本):默认为 -H gnu,它与 -H oldgnu 格式没有太大区别。
  • -H ustar 是可移植的 POSIX.1-1988 格式,一些限制包括最大 256 个字符的文件名,最大 8G 文件大小;支持特殊文件,但不支持稀疏文件。似乎也不支持 xattrs 和 ACL(其他 tar 格式旨在处理 ACL,但请参阅 下面的评论


本地复制示例

sudo tar -cf- [--one-file-system] /source | sudo tar -xp[v]f- -C /target

可选标志是

  • --one-file-system: 停留在 /source 所在的卷上。这可能是您期望的行为,也可能不是。请注意,此功能在任何情况下在 BusyBox tar 中都不可用,但在其他一些 tar 实现中可用。
  • -v: 详细模式

使用 tar 在 cpio 样式中的示例(为此,请参见下文)

cd /source sudo find . [-xdev] -depth [-print0] | sudo tar -cf- -T- [--null] | sudo tar -xp[v]f- -C /target

以下示例添加了 -z 标志,以使用 gzip 压缩输出。如果您有快速连接,则可以省略此标志;或者,您可以对 bzip2 使用 -j。复制到远程计算机的示例

sudo tar -czf- [--one-file-system] /source | ssh root@machine "tar -xpz[v]f- -C /target"

从远程计算机复制的示例

ssh root@machine "tar -czf- [--one-file-system] /source" | sudo tar -xpz[v]f- -C /target

cpio

cpio 在四种模式之一中运行

  • -o -H newc: 在标准输出上创建归档文件(或 -F archive),包括从标准输入提供的文件名(如 tar -cf- -T-
-H newc: (在 Mac 上,-H sv4cpio 和/或 -c)指定使用 SVR4 ASCII 格式,这是在 BusyBox 中创建归档文件所必需的
  • -i: 从标准输入接收归档文件(或 -F archive),提取 curdir 下指定的模式(如 tar -xf-
  • -t: (在某些系统上,可能需要 -it)从标准输入接收归档文件(或 -F archive),将内容列出到标准输出(如 tar -tf-
  • -p /target: 从标准输入接收文件列表(或 -F archive),将它们复制到 /target 下(如 tar -cf- -T- | tar -xf- -C /target


tar vs cpio

  • 如果您有包含/排除项,则使用 find 比使用 GNU tar 的不熟悉且不可移植的选项更容易
  • cpio 处理特殊文件(块设备和字符设备、fifo 等),传统的 tar(-H v7 格式)不处理,也不存储符号所有者/组
  • 提取硬链接时,tar 必须始终包含第一个
  • tar 和 -H newc cpio 格式处理 32 位 inode;尽管一些较旧的 cpio 格式不处理
  • -H newc cpio 格式具有最大 1024 个字符的文件名(尽管 GNU cpio 可以处理任意长度)和最大 4G 文件大小。可移植的 -H ustar tar 格式具有最大 256 个字符的文件名和最大 8G 文件大小限制
  • 在某些实现中,cpio 无法正确复制超过 2G 的文件。不清楚哪些实现/版本受到如此限制
  • 一些 tar 格式应该处理 acls,但是 实际上这似乎不是很可靠。不确定 cpio 的情况如何。已知 rsync 在这种情况下效果很好


本地复制示例

cd /source sudo find . [-xdev] -depth [\! -path ./lost+found] [-print0] | sudo cpio -pdm[vul] [-0] /target


标志是

  • -xdev: 停留在 /source 所在的卷上;这可能是您期望的行为,也可能不是
  • \! -path ./lost+found: 省略空 ./lost+found! 仅在某些 shell 中需要转义,并且此序列可能会重复
  • -print0 ... -0: 允许处理包含嵌入 \n 的文件名,在 BusyBox cpio 或 Mac 上不可用
  • -d: 创建前导目录,如 mkdir -p
  • -m: 保留文件的原始 mtime
  • -v: 详细模式
  • -u: 覆盖现有文件,即使它们比正在复制的文件更新
  • -l: 创建硬链接而不是复制。这可能是您期望的行为,也可能不是。请注意,此功能在任何情况下在 BusyBox cpio 中都不可用,但在其他一些 cpio 实现中可用。

其他标志是

  • -oA -F archive: 附加到现有归档文件(不在 BusyBox 或 BSD 上)
  • -L: 跟随符号链接(不在 BusyBox 上)
  • --sparse: 将包含零块的文件作为稀疏文件写入(仅限 Gnu)


复制到远程计算机的示例

cd /source sudo find . [-xdev] -depth [-print0] | sudo cpio -o -H newc [-0] | [gzip -3 |] ssh root@machine "cd /target; gunzip | cpio -idm[vu]"

rsync

rsync 必须安装在源计算机和目标计算机上。示例

rsync -a[vzx] --delete [--numeric-ids] [-HAX] [--exclude=/proc --exclude=/dev --exclude=/sys] /source/ [root@machine:]/target

请注意,/source/ 上的尾部 / 至关重要,如果您希望 /target 最终成为 /source 的克隆。

标志是

  • -v: 详细模式
  • -z: 在传输期间压缩数据
  • -x--one-file-system: 跳过不同卷上的子目录
  • --numeric-ids: rsync 的默认设置是使用符号用户/组名
  • -H--hard-links: 保留复制数据中的硬链接,这可能很昂贵,并且不会破坏 /target 上现有的硬链接,除非 rsync 需要将更新的数据写入某些链接文件
  • -A--acls: 保留 ACL
  • -X--xattrs: 保留 xattrs
  • -8--8-bit-output: 即使文件名中的字符在当前语言环境中无效,也不要转义它们
  • --partial: 保留部分传输的文件
  • --inplace: 就地覆盖现有文件
    rsync 的默认行为是写入新文件,并在完成后将它们移动到位。这会破坏现有文件可能具有的任何硬链接,并使写时复制文件系统将文件视为全新的文件。--inplace 指定了一种替代行为,即直接将更新的数据写入现有文件。
  • -h--human-readable: 以更美观的形式报告统计信息(使用一次表示 10 的幂,两次表示 2 的幂)
  • --progress: 显示每个传输文件的进度,暗示 -v
  • -n--dry-run

rsync 的完整手册页

rsync 的优势

  • 像 cp 一样,可以处理 ACL 和 xattrs。许多 tar 和 cpio 实现不能
  • 像 cpio 一样,可以选择通过网络工作
  • 可以恢复未完成的传输,并且如果数据被多次复制,则可以进行增量更新


包含/排除传输

  • --include=pattern[/]
  • --exclude=pattern[/]

这些中的每一个都可以重复。pattern 可以包含 ***?[a-z]。尾部 dir/*** 匹配 dir 及其内容。如果 pattern 包含 ** 或(非尾部)/,则它与来自 /target 的完整路径匹配,否则它仅与最终路径元素匹配。

lvm

“这就是我喜欢 LVM 的原因之一。只需将新磁盘添加到卷组,将逻辑卷从旧磁盘 pvmove 到新磁盘,[稍等片刻],从卷组中删除旧磁盘,然后从系统中删除。如果要替换引导磁盘,则还需要更新引导加载程序。”

请参阅 使用 LVM 设置逻辑卷


其他工具

cd /source pax -pe -rw -v [-X] -YZ . /target