迁移数据
我们比较了几种复制/迁移大量数据的方法。目的是保留所有文件权限和元数据,这需要在源文件系统和目标文件系统上都具有 root 访问权限。
我们包含了一些关于 BusyBox 实现中不可用的选项的信息,因为您可能会将数据复制到/从安装了其他 Unix 工具的系统,这些工具确实提供了这些选项。

位复制方法
如果您的源数据占据整个分区(即,该分区上没有其他内容),并且您的目标分区大小相同或更大,并且您愿意让它使用与源相同的文件系统,那么一种选择是位复制整个源分区
从 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 格式。

完成后,targetpart 上的文件系统可能占用的空间少于 targetpart 上的可用总空间。您可能需要使用 像 resize2fs 这样的工具来扩展分区。
更高级别的方法
我们将讨论的其他选项假设目标文件系统已格式化并挂载为 /target。
如果您需要从正在运行的系统复制易失性数据,您可能需要从 lvm 快照复制,或者从单用户模式或 LiveCD 或其他启动介质进行复制,以便您的源数据在复制期间不被使用。如果您想从 /home 或类似位置复制,则无需采取此类预防措施。
如果您要复制完整的文件系统,您可能只想复制 /sys 和 /proc 挂载点,而不是它们的当前内容。请记住复制 /boot 和 /dev 和 /tmp,最后两个可能需要特别注意。注意其他挂载点(例如 /mnt、/media)和基于 RAM 的文件系统(例如 /run 和 /lib/rc/init.d)。

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 选项,并且可能缺少 --preserve
的 context
和 xattr
选项。它将保留硬链接:如果 /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 所在的卷上。这可能是您期望的行为,也可能不是。请注意,此功能在任何情况下在 BusyBoxtar
中都不可用,但在其他一些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
的文件名,在 BusyBoxcpio
或 Mac 上不可用-d
: 创建前导目录,如mkdir -p
-m
: 保留文件的原始 mtime-v
: 详细模式-u
: 覆盖现有文件,即使它们比正在复制的文件更新-l
: 创建硬链接而不是复制。这可能是您期望的行为,也可能不是。请注意,此功能在任何情况下在 BusyBoxcpio
中都不可用,但在其他一些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 的优势
- 像 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