手动克隆/重新创建虚拟磁盘

mki*_*ton 7 linux virtualbox partitioning virtual-machine

我正在尝试以相当手动的方式克隆虚拟磁盘映像。到目前为止,我的方法论概述如下:

  1. 在 VirtualBox 中使用 120GB 硬盘创建虚拟机(管理程序和硬盘大小无关紧要,主要是为了完整性和与我的其余问题的一致性,例如分区大小)
  2. 在虚拟机上安装 Ubuntu 12.04.3
  3. 关闭虚拟机
  4. 挂载与虚拟机关联的虚拟硬盘
  5. 提取操作系统文件和数据以存储在目录中
  6. 保存虚拟硬盘元数据
  7. 创建新的虚拟磁盘并从 (6) 恢复分区和引导信息
  8. 将数据从(5)恢复到正确的分区

问题

我复制的 VM 无法启动。Grub 似乎复制,并且似乎承认我的根分区(安装了 Ubuntu)。我可以通过 Grub 启动一次并出现紫色屏幕,就好像 Ubuntu 即将加载一样。然后它停止。之后,我可以启动到 Grub,选择我的操作系统,然后我会看到一个闪烁的命令行光标。无法输入。我怀疑在克隆过程中我遗漏了一些东西(有关更多详细信息,请参见下文)。注意:我使用的是 grub2,而不是旧版。

你为什么做这个?

作为合同要求的一部分,我需要将虚拟磁盘存储在版本控制中。在版本控制中拥有一个巨大的二进制 blob(虚拟磁盘)是一种痛苦,主要用于 clone(git)/checkout(svn),但也用于差异。我已经考虑过压缩到多个文件,但我需要能够操作上面 (5) 中提取的操作系统/数据。请注意,我的 VCS 存储库仍然需要构建完整 VM 所需的所有信息。

细节

重现我所描述的内容的详细说明:

  1. 创建一个 VM 并启动 Ubuntu Live CD
  2. 选择“试用 Ubuntu”
  3. 打开终端
  4. 创建 msdos 分区: sudo parted /dev/sda mklabel msdos
  5. 创建一个 2GB 的交换文件:sudo parted /dev/sda mkpart primary linux-swap 2048s 4198399s
  6. 将驱动器的其余部分用作根分区: sudo parted /dev/sda mkpart primary ext4 4198400s 100%
  7. 重启机器,选择“安装 Ubuntu”
  8. 选择高级分区选项
  9. 双击swap分区,选择作为swap使用
  10. 双击根分区,选择格式化并用于根(/)挂载点

现在,执行以下操作来克隆磁盘:

# Set up some parameters
ORIG_DEV="/dev/nbd0"
ORIG_MNT=$(mktemp -d)
ORIG_IMG="orig.vdi" 
CLONE_DEV="/dev/nbd1"
CLONE_MNT=$(mktemp -d)
CLONE_IMG="clone.vdi"
qemu-img info $ORIG_IMG # save the "virtual size" output (in bytes) in the
                        # VIRT_SIZE variable in the next command
VIRT_SIZE="128849018880"

# Create the clone disk
qemu-img create -f vdi $CLONE_IMG $VIRT_SIZE

# Use qemu to make both disks accessible
modprobe nbd
qemu-nbd -c $ORIG_DEV $ORIG_IMG
qemu-nbd -c $CLONE_DEV $CLONE_IMG

# Set up the clone disk partition table and partitions
parted $CLONE_DEV mklabel msdos
parted $CLONE_DEV mkpart primary linux-swap 2048s 4198399s
parted $CLONE_DEV mkpart primary ext4 4198400s 100%

# Format the clone disk partitions and clone the UUIDs
mkswap $CLONE_DEVp1 -U $(blkid $ORIG_DEVp1 -s UUID -o value)
mkfs.ext4 $CLONE_DEVp2 -U $(blkid $ORIG_DEVp2 -s UUID -o value)

# Mount both disks and copy root from the original to the clone
mount $CLONE_DEVp2 $CLONE_MNT
mount $ORIG_DEVp2 $ORIG_MNT
find $ORIG_MNT -maxdepth 1 -mindepth 1 | xargs -I{} cp -ar {} $CLONE_MNT
umount $ORIG_MNT
umount $CLONE_MNT

# Copy the boot sector and partition table from the original
dd if=$ORIG_DEV of=$CLONE_DEV bs=$((2048*512)) count=1

# Disconnect the disks
qemu-nbd -d $CLONE_DEV
qemu-nbd -d $ORIG_DEV
Run Code Online (Sandbox Code Playgroud)

你还尝试了什么?

  1. grub-install --root-directory=/path/to/clone/device/boot/ /dev/clone_device. 这在正确的设备上安装了 Grub,但带有我主机的设备详细信息。VM 无法启动。
  2. chroot 到克隆磁盘,然后 grub-install。遇到麻烦,因为我必须能够使用 64 位主机来克隆 32 位来宾。这似乎是一个充满希望的调查途径,但我对如何实现这一目标感到困惑。
  3. 挂载虚拟磁盘,使用 将所有文件移出数据分区mv,将数据和交换分区归零(dd if=/dev/zero of=/dev/nbd0p2)并压缩虚拟磁盘(使用VBoxManage modifyhd clone.vdi --compress)。磁盘开始在我的主机文件系统上扩展,因为它用空白空间填充它(哈!)。dd当我意识到发生这种情况时,我停下来,然后压缩了磁盘映像。它仍然超过3GB。(我还没有尝试过使用 gzip/bzip,我将在今晚开始尝试。我还将尝试让 dd 擦除运行完成,但我更喜欢耗时较少的解决方案,即使可行) .
  4. e2image。请参阅我的另一个问题:e2image restore file system metadata。我还没有解决这个问题。请注意,我在Detail部分提供的步骤,包括分区创建、格式化和引导扇区复制,但复制根分区之前,生成一个与 e2image 创建的图像文件大小非常相似的图像文件。
  5. 启动到另一个 VM 以 chroot 进入这个 VM 以运行 grub-install。我实际上并没有这样做,但我把它包括在这里以防有人建议它。对于我的用户来说,我需要重新组合虚拟机才能编写脚本;这排除了涉及的设置过程。
  6. 安装 extlinux 而不是 Grub。虽然不成功,但此练习表明(我认为!)引导加载程序已成功从我的分区加载 ram 磁盘,但此时卡住了。

如果你已经走到这一步,谢谢你!任何有关调查途径的建议,无论多么不详细,都将不胜感激。提前致谢。

Dre*_*pin 3

也许您已经尝试过,也许还没有。但是您是否尝试过在“复制的虚拟机”中从 Live CD 重新安装 Grub2?我读到的所有内容听起来就像您正在从主机安装 Grub2。

  • 一旦出现重复的虚拟机无法启动的情况
  • 将Live CD(例如Ubuntu安装盘)挂载到虚拟机
  • 启动 VM 并按 F12 从 Live CD 启动
  • 从命令行重新安装 grub(在 VM 内)

如果您想自动化该过程,您可以使用VBoxManage安装自定义 Ubuntu Live CD 来运行脚本以在启动时重新安装 Grub2。

VBoxManage storageattach "io" --storagectl "IDE Controller" \
--port 1 --device 0 --type dvddrive --medium debian-6.0.2.1-i386-CD-1.iso
Run Code Online (Sandbox Code Playgroud)

示例来源

希望不会太过时,help.ubuntu.com 上有一个用于自定义 Live CD 的指南askubuntu.com 上有一个 Stack Exchange 问题/答案,涉及向自定义 Live CD 添加启动脚本