Linux有四个你应该考虑的磁盘克隆解决方案:
- dd
- Partimage
- Partclone
- Clonezilla
今天讲讲dd的用法,之所以先说dd因为简单易用而且兼容性好,首选。
使用dd
dd是一个简单,多功能,强大的工具。可以用来把数据按照块顺序从源位置复制到目标位置,并且不管文件类型和操作系统。一种快捷的方法就是从live环境中使用dd,比如从Live CD上。
警告:像任何这种类型的命令一样,你使用的时候需要非常小心。这个命令可以毁坏数据。记住输入文件(if=)和输出文件(of=)的顺序,不能颠倒!时刻保证目标磁盘或者分区(of=)的容量等于或大于源位置(if=)的容量。
克隆一个分区
从物理磁盘/dev/sda 分区1 到物理磁盘/dev/sdb 分区2。
# dd if=/dev/sda1 of=/dev/sdb1 bs=512 conv=noerror,sync
警告:如果输出文件of=(上面例子的sdb1)不存在,dd会创建一个这个名字的文件,然后开始填充你的root文件系统!
克隆一个完整的硬盘
从物理磁盘/dev/sdX到物理磁盘/dev/sdY
# dd if=/dev/sdX of=/dev/sdY bs=512 conv=noerror,sync
这个命令会克隆整个磁盘,包括MBR(因此也包含bootloader),所有分区,UUID和数据。
- noerror 指定dd命令继续操作,忽略所有的读错误。dd默认行为是会在任何错误时候停止
- sync 如果有读错误,把输入的块填0,所以数据偏移在sync设置时保留
- bs=512 设置块大小512bytes,对于硬盘来说是“经典”的块大小。只有在你的硬盘是4Kb块大小时,你才可以用4096而不是512。同时,请阅读下面的警告,因为这个不仅仅是“块大小”,它同时会影响到如何处理读错误。
警告:你指定的块大小会影响到如何处理读错误。请读以下内容。
dd工具有”输入块大小“(IBS)和”输出块大小“(OBS)。当你设置bs,其实是同时设置了IBS和OBS。通常情况下,如果你的块大小是1Mb,dd会读取1024*1024bytes,然后写同样数量的bytes。但是如果一个读错误发生,事情就变错误了。许多人看起来像是认为如果设置了noerror,sync,dd会”把读错误填0”,但其实事实不是这样。dd会按照文档的描述,在完成读命令后,把OBS填满到IBS,这就意味着在块末尾添0。也就是说,对于一个磁盘来说,整个1Mb的有效数据会变混乱,因为对于一个512byte读错误,一开始读到的数据:12ERROR89会变成128900000,而不是12000089。
如果你很乐观,你的磁盘不会有任何的错误,那你可以使用更大的块大小,这样会成倍增加拷贝速度。比如,在一个单赛扬2.7GHz的系统上,把bs从512改变到64K会把拷贝速度从35MB/s增加到120MB/s。但是记住源磁盘上的读错误会导致目标磁盘上的块错误。比如,一个512byte的读错误会破坏整个64Kb的输出块数据。
技巧:如果你想查看dd的进度,用status=progress选项
补充:
- 重新获得ext2/3/4文件系统的唯一UUIDs,在每个分区上使用 tune2fs /dev/sdXY -U random
- dd导致分区表的变化没有注册到kernel中。如果要不重启让改变生效,使用工具诸如partprobe(GNU Parted)
备份MBR
MBR保存在磁盘的第一个512bytes中,包含以下三部分。
- 开始446bytes包含boot loader
- 接下来64bytes包含分区表(每项16bytes,4项,每个主分区对应一项)
- 最后2bytes包含identifier
保存分区表到mbr.img:
# dd if=/dev/sdX of=/path/to/mbr_file.img bs=512 count=1
恢复(谨慎操作,恢复可能会损坏现有的分区表,以至于无法访问磁盘上的所有数据):
#dd if=/path/to/mbr_file.img of=/dev/sdX
如果你只是想恢复boot loader,而不是主分区表,只是恢复MBR的前446bytes数据:
#dd if=/path/to/mbr_file.img of=/dev/sdX bs=446 count=1
只恢复分区表,使用:
#dd if=/path/to/mbr_file.img of=/dev/sdX bs=1 skip=446 count=64
同样,你也可以从一个完整的dd磁盘镜像中获得MBR:
#dd if=/path/to/mbr_file.img of=/dev/sdX bs=1 bs=512 count=1
创建磁盘镜像
1. 从live介质启动
2. 确保没有分区挂载在源硬盘上
3. 挂载外置硬盘
4. 备份硬盘
把源盘中的内容压缩后放在本地磁盘目标位置
#dd if=/dev/sdX conv=sync,noerror bs=64k | gzip -c > /path/to/backup.img.gz
如果需要(例如外置硬盘是FAT32时),把磁盘镜像拆分成多个卷(参考split man页面)
#dd if=/dev/sdX conv=sync,noerror bs=64K | gzip -c| split -a3 -b2G - /path/to/backup.img.gz
如果本地磁盘没有足够空间,你可以通过ssh发送镜像
#dd if=/dev/sdX conv=sync,noerror bs=64K | gzip -c | ssh user@local dd of=backup.img.gz
5. 保存磁盘结构信息,以便解析保存在镜像中的分区表。其中最重要的部分是柱大小
#fdisk -l /dev/sdX > /path/to/list_fdisk.info
补充:你可能想和使用和备份硬盘缓存一样容量的块大小。例如,8M缓存对应bs=8192K。本文中提到的64Kb比默认bs=512好,但使用更大的bs=会更快
恢复系统
#gunzip -c /path/to/backup.img.gz | dd of=/dev/sdX
当镜像拆分过,使用这样的命令:
#cat /path/to/backup.img.gz* | gunzip -c | dd of=/dev/sdX