在Debian系统中,磁盘映像技术是管理和维护数据存储的一个强大工具,允许用户创建整个磁盘或分区的快照,这些快照可以用于备份、恢复系统、或者在不同设备间迁移数据。本教程将介绍一系列的磁盘映像操作技巧,包括如何制作和处理各种类型的磁盘映像文件。
一、制作磁盘映像文件
一个未挂载设备(例如,第二个 SCSI 或 串行 ATA 设备 “/dev/sdb”)的磁盘映像文件 “disk.img” 可以使用 cp(1) 或 dd(1) 通过下列方式建立。
# cp /dev/sdb disk.img # dd if=/dev/sdb of=disk.img
传统 PC 中位于主 IDE 硬盘第一扇区的主引导记录(MBR)的磁盘映像可以使用 dd(1) 通过下列方式建立。
# dd if=/dev/hda of=mbr.img bs=512 count=1 # dd if=/dev/hda of=mbr-nopart.img bs=446 count=1 # dd if=/dev/hda of=mbr-part.img skip=446 bs=1 count=66
- “mbr.img”:带有分区表的 MBR;
- “mbr-nopart.img”:不带分区表的 MBR;
- “mbr-part.img”:仅 MBR 的分区表。
如果使用 SCSI 或 串行 ATA 设备作为启动硬盘,需要使用 “/dev/sda” 替代 “/dev/hda”。如果要建立原始硬盘的一个硬盘分区的映像,需要使用 “/dev/hda1” 等替代 “/dev/hda”。
二、直接写入硬盘
磁盘映像文件 “disk.img” 可以通过下列方式写入到一个匹配大小的未挂载设备(例如,第二个 SCSI 设备 “/dev/sdb”。
# dd if=disk.img of=/dev/sdb
相似地,硬盘分区映像文件 “partition.img” 可以通过下列方式写入到匹配大小的未挂载分区(例如,第二个 SCSI 设备的第一个分区 “/dev/sdb1”)。
# dd if=partition.img of=/dev/sdb1
三、挂载磁盘映像文件
可以使用循环设备通过下列方式挂载和卸载包含单个分区映像的磁盘映像 “partition.img”。
# losetup -v -f partition.img Loop device is /dev/loop0 # mkdir -p /mnt/loop0 # mount -t auto /dev/loop0 /mnt/loop0 ...hack...hack...hack # umount /dev/loop0 # losetup -d /dev/loop0
可以简化为如下步骤。
# mkdir -p /mnt/loop0 # mount -t auto -o loop partition.img /mnt/loop0 ...hack...hack...hack # umount partition.img
可以使用 循环设备 挂载包含多个分区的磁盘映像 “disk.img” 的每个分区。因为循环设备默认不管理分区,因此我们需要通过下列方式重新设置它。
# modinfo -p loop # verify kernel capability max_part:Maximum number of partitions per loop device max_loop:Maximum number of loop devices # losetup -a # verify nothing using the loop device # rmmod loop # modprobe loop max_part=16
现在循环设备可以管理多达 16 个分区。
# losetup -v -f disk.img Loop device is /dev/loop0 # fdisk -l /dev/loop0 Disk /dev/loop0: 5368 MB, 5368709120 bytes 255 heads, 63 sectors/track, 652 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Disk identifier: 0x452b6464 Device Boot Start End Blocks Id System /dev/loop0p1 1 600 4819468+ 83 Linux /dev/loop0p2 601 652 417690 83 Linux # mkdir -p /mnt/loop0p1 # mount -t ext4 /dev/loop0p1 /mnt/loop0p1 # mkdir -p /mnt/loop0p2 # mount -t ext4 /dev/loop0p2 /mnt/loop0p2 ...hack...hack...hack # umount /dev/loop0p1 # umount /dev/loop0p2 # losetup -d /dev/loop0
或者,也可以使用 kpartx 软件包中的 kpartx(8) 建立 设备映射设备来达到相同的效果。
# kpartx -a -v disk.img ... # mkdir -p /mnt/loop0p2 # mount -t ext4 /dev/mapper/loop0p2 /mnt/loop0p2 ... ...hack...hack...hack # umount /dev/mapper/loop0p2 ... # kpartx -d /mnt/loop0
也可以使用循环设备利用偏移量来跳过 MBR 等,来挂载此类磁盘映像的单个分区。但这更加容易出错。
四、清理磁盘映像文件
使用下面的方式,一个磁盘映像文件 “disk.img” 能够清理掉所有已经删除的文件,成为一个干净的稀疏映像 “new.img”。
# mkdir old; mkdir new # mount -t auto -o loop disk.img old # dd bs=1 count=0 if=/dev/zero of=new.img seek=5G # mount -t auto -o loop new.img new # cd old # cp -a --sparse=always ./ ../new/ # cd .. # umount new.img # umount disk.img
如果 “disk.img” 位于 ext2、ext3 或 ext4,也可以像下面那样使用 zerofree 软件包中的 zerofree(8)。
# losetup -f -v disk.img Loop device is /dev/loop3 # zerofree /dev/loop3 # cp --sparse=always disk.img new.img
五、制作空的磁盘映像文件
按下面的方式使用 dd(1) ,可以制作一个大小为 5GiB 的空磁盘映像文件。
$ dd bs=1 count=0 if=/dev/zero of=disk.img seek=5G
专业的 fallocate(8) 可以在这里被使用,用来替代使用 dd(1)。
按下面的方式使用环回设备,能够在这个磁盘映像”disk.img”上创建 ext4 文件系统。
# losetup -f -v disk.img Loop device is /dev/loop1 # mkfs.ext4 /dev/loop1 ...hack...hack...hack # losetup -d /dev/loop1 $ du --apparent-size -h disk.img 5.0G disk.img $ du -h disk.img 83M disk.img
对于 “disk.img”,它的文件大小是5.0 GiB,而它实际磁盘使用仅仅是 83MiB.这个差距可能是由于 ext4 里面有稀疏文件.
注意:稀疏文件的实际磁盘使用会随着数据的写入而增加。
回环设备或设备映射设备上使用类似的操作,在这些设备挂载后, 能够使用 parted(8) 或 fdisk(8)对这个磁盘映像”disk.img”进行分区,能够使用 mkfs.ext4(8), mkswap(8)在上面创建文件系统等.
六、制作ISO9660镜像文件
“源目录”下的目录树可以通过如下所示的 cdrkit 提供的 genisoimage(1) 命令来制作 ISO9660 镜像文件,”cd.iso”。
# genisoimage -r -J -T -V volume_id -o cd.iso source_directory
类似的,可引导的 ISO9660 镜像文件,”cdboot.iso”, 能够从 debian-installer 类似目录树 “source_directory” 制作,方式如下。
# genisoimage -r -o cdboot.iso -V volume_id \ -b isolinux/isolinux.bin -c isolinux/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table source_directory
这里的 Isolinux boot loader是用于启动的.按下面的方式,可以直接从光驱设备计算 md5sum 值,并制作 ISO9660 镜像。
$ isoinfo -d -i /dev/cdrom CD-ROM is in ISO 9660 format ... Logical block size is: 2048 Volume size is: 23150592 ... # dd if=/dev/cdrom bs=2048 count=23150592 conv=notrunc,noerror | md5sum # dd if=/dev/cdrom bs=2048 count=23150592 conv=notrunc,noerror > cd.iso
注意:为了得到正确结果,必须小心避免 Linux ISO9600 文件系统预读 bug。
七、直接写入文件
对于由 cdrkit 提供的 wodim(1) 来讲,DVD 仅仅是一个大的 CD。能够通过如下所示的命令找到可用的设备。
# wodim --devices
然后将空的 CD-R 插入 CD 驱动器并且把 ISO9660 镜像文件,”cd.iso” 写入到设备中,例如用如下所示的 wodim(1) 将数据写入到 “/dev/hda” 设备。
# wodim -v -eject dev=/dev/hda cd.iso
如果用 CD-RW 代替 CD-R,用如下所示的命令来替代。
# wodim -v -eject blank=fast dev=/dev/hda cd.iso
如果桌面系统自动挂载 CDs,在使用 wodim(1) 之前在终端里面用 “sudo umount /dev/hda” 卸载它。
八、挂载ISO9660镜像文件
如果 “cd.iso” 包含一个 ISO9660 镜像, 下面的命令手工挂载这个文件到 “/cdrom”.
# mount -t iso9660 -o ro,loop cd.iso /cdrom
现代桌面系统能够自动挂载可移动介质,如按 ISO9660 格式化的 CD