使用分区表将分区的映像转换为磁盘的映像


20

我有使用生成的现有分区的图像dd if=/dev/sdXN of=image.bin。现在,我想将此映像用作虚拟机的基础。我知道如何将图像转换为VirtualBox可以使用的格式。

问题是“磁盘”映像实际上只是一个分区的映像,因此不包含MBR或分区表。这使得启动虚拟机非常困难。

给定分区的映像,是否有一种简单的方法来创建适当的磁盘映像(包括分区表)?

Answers:


13

您可以在主机上执行此操作。大多数工具(例如)fdisk都可以在文件上运行,并kpartx允许您访问文件中的分区。

  1. 创建一个新的空100GiB稀疏映像(使其稍大于分区映像的大小)

    dd if=/dev/zero of=myvm.img bs=1G count=0 seek=100
    
  2. 用分区图像文件 fdisk

    fdisk myvm.img
    
  3. 使映像文件中的分区对于单个设备可用

    sudo kpartx -a myvm.img
    
  4. 将分区映像复制到分区

    sudo cp image.bin /dev/mapper/loop0p1
    
  5. 扩展文件系统以填充整个分区

    sudo resize2fs /dev/mapper/loop0p1
    
  6. 关闭分区

    sudo kpartx -d myvm.img
    
  7. 拆卸环回设备

    sudo losetup -D
    

这会不会使映像中创建的分区的长度与映像分区的长度“不匹配”?有办法解决吗?而且,一个“足够智能”的文件系统管理器是否可以说它没有使用整个分区的大小,而是自行扩展以适合它?
杀手主义者2012年

@killermist更新了答案。
mgorven 2012年

这是一个很好的答案。您知道避免复制整个过程的任何方法吗?
米卡·菲舍尔

@MikaFischer不幸的是没有,因为分区表需要在分区之前存在,而且我不知道任何将数据添加到文件中的机制。
mgorven 2012年

我认为Harun的答案更好,因为它易于执行并且可以编写脚本。
philcolbourn 2014年

9

我敢肯定,原来的问题早就解决了,但是对于任何有类似问题的人来说:

避免复制整个映像的一种方法是创建一个.vmdk格式的映像,该映像引用分区表和分区内容的单独扩展区文件。

我前一阵子的测试中的.vmdk文件中有这个代码段:

RW 63 FLAT "parttable.bin" 0
RW 585937489 FLAT "partition-image.bin" 63

这意味着从偏移文件0开始的63个扇区是从原始文件“ parttable.bin”中读取的,而扇区63及以上的扇区是从原始分区转储“ partition-image.bin”中读取的。(当然,将63替换为第一个分区的实际偏移量,最近通常为2048)。

最终结果是,从VBox内部看,好像您已将分区表放在分区映像的前面,而不必进行冗长的复制操作。

从VM内对驱动器进行分区,如果偏移正确,则应该在新创建的分区内看到分区映像内容。


2
我认为,如果partition-image.bin是分区映像,则第二行的“ 63”需要为0。我刚刚做了类似的事情,我需要将分区映像文件中的偏移量设置为零。philatwarrimoo.blogspot.com.au/2014/01/...
philcolbourn


天才。我只需要这样做即可在Linux主机上为VM使用Windows分区,这是唯一起作用的方法,使用@philcolbourn中的步骤:superuser.com/a/804396/93066
bmaupin 2014年

vmdk文件的其余部分应该是什么?
gozzilli '17

1
@gozzilli文件的其余部分是一堆细节,例如文件版本号,磁盘适配器类型,uuid和磁盘几何形状。我不知道该怎么写这些位。我建议仅使用一种工具来创建指向磁盘映像的vmdk,然后仅修改描述从何处获取额外分区头的行。
哈伦

3

有趣的问题。这就是我要做的:

  1. 用适当大的磁盘创建VM,然后从恢复CD引导它。
  2. 以某种方式访问​​您现有的磁盘映像(nfs,cif等)。
  3. 在虚拟机的本地磁盘上创建所需的分区。
  4. 使用dd将分区映像写入vm磁盘上的分区。

完成此操作后,您将需要更新引导加载程序。假设您正在使用GRUB,请挂载新写入的分区,然后将chroot插入其中并运行update-grub(尽管要小心,您可能需要调整其配置文件才能正常工作)。

祝好运!


2

您可以使用GParted调整文件系统的大小。

创建测试图像:

dd if=/dev/zero of=extfs bs=1M count=20
mkfs.ext4 extfs

我没有使用resize2fs,因为它会调整文件的大小,而不是留下可用空间。

sudo losetup /dev/loop0 extfs
sudo ln -s /dev/loop0 /dev/loop0p1 # needed for GParted to be able to resize it
gksudo gparted /dev/loop0

开始时释放1 MB。

sudo rm /dev/loop0p1
sudo losetup -d /dev/loop0

最后,创建分区表。

fdisk extfs

将第一个扇区设置为2048(2048个扇区* 512 B /扇区= 1MB),最后一个扇区为默认值(即图像结尾)。


1

我个人更喜欢附加使用dd

我在这里假设512字节的扇区。可能存在2048字节扇区的情况,因此只需交换数字并进行数学运算即可。

在每种情况下,我都使用一个512MB的测试文件,例如:

dd if=/dev/zero of=testfs.img bs=512 count=1M mkfs.ext4 testfs.img

MBR

构图

我个人更喜欢在开头添加第一个MB(2048个扇区):

dd if=testfs.img skip=2048 bs=512 of=full.img

最后运行fdisk创建分区表(或自己复制),我使用默认值创建了1个分区。

验证中

要进行验证,请创建循环分区并自动检测:

sudo losetup -fP full.img

file在生成的分区回送设备上运行:

sudo file -s /dev/loop2p1 /dev/loop2p1: Linux rev 1.0 ext4 filesystem data, UUID=ae2945fd-54b5-486f-8dd0-9b18d6ae01b4 (extents) (large files) (huge files)

GPT

构图

我个人更喜欢在开头MBR的开头添加第一个MB(2048个扇区,因为gdisk将默认为该数字,因为它已对齐1 MB),在结尾处附加34个扇区(对于完整MB则为2048个) GPT(终端行业可能有所不同)。省略最后的GPT可能会丢失您的数据:

dd if=testfs.img skip=2048 bs=512 of=full.img dd if=/dev/zero seek=1050624 bs=512 of=full.img count=34

最后运行gdisk创建分区表(或自己复制),我使用默认值创建了1个分区。

验证中

要进行验证,请创建循环分区并自动检测:

sudo losetup -fP full.img

file在生成的分区回送设备上运行:

sudo file -s /dev/loop2p1 /dev/loop2p1: Linux rev 1.0 ext4 filesystem data, UUID=ae2945fd-54b5-486f-8dd0-9b18d6ae01b4 (extents) (large files) (huge files) 此方法可确保不进行猜测,调整大小或手动对齐。


您如何在gpt中找到图像的末端扇区
Anwar,

当我运行这个时,sudo file -s /dev/loop11p1我得到了/dev/loop11p1: data。以前是ext4文件系统。结果得到的full.img较小。我认为您的解决方案已经颠倒了。
安瓦尔

我认为您的意思是seek=2048在此命令中dd if = testfs.img skip = 2048 bs = 512 of = full.img
Anwar
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.