今天收到大佬给的一个VMDK的debian bookworm系统的虚拟机,在测试实时性时发现极其出色,故因此想把改VMDK转化成可以直接安装在实体机器上的Linux操作系统。
这里我们需要把VMDK转换成IMG,我的初步构想是将img文件制作成U盘启动,然后再烧录到电脑的硬盘中
qemu-img convert -O raw test.vmdk test.img
第一步完成后,可以直接将test.img烧录到U盘并启动,但是我发现老款的机子可以启动,新款机子识别不到U盘,看了一下test.img的属性,好家伙是MBR,不支持UEFI启动,怪不得新的机子识别不到,因此我这里需要重新制作一个UEFI的镜像,不然启动的时候BIOS识别不到U盘
damn@damn-virtual-machine:~$ fdisk -l test.img
Disk test.img: 25 GiB, 26843545600 bytes, 52428800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x338c503f
Device Boot Start End Sectors Size Id Type
test.img1 * 2048 50427903 50425856 24G 83 Linux
test.img2 50429950 52426751 1996802 975M 5 Extended
test.img5 50429952 52426751 1996800 975M 82 Linux swap / Solaris
damn@damn-virtual-machine:~$ gdisk -l test.img
GPT fdisk (gdisk) version 1.0.8
Partition table scan:
MBR: MBR only
BSD: not present
APM: not present
GPT: not present
***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory.
***************************************************************
Disk test.img: 52428800 sectors, 25.0 GiB
Sector size (logical): 512 bytes
Disk identifier (GUID): 6DD1C871-8298-4C6A-88DB-117B7926645D
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 52428766
Partitions will be aligned on 2048-sector boundaries
Total free space is 6077 sectors (3.0 MiB)
Number Start (sector) End (sector) Size Code Name
1 2048 50427903 24.0 GiB 8300 Linux filesystem
5 50429952 52426751 975.0 MiB 8200 Linux swap
由于之前的经验,我将Linux分区挂载在/mnt下,看了一下Linux系统的大小,文件不过4G左右,因此我新建一个8G的img,建立好以后,我们需要用loop的方式挂载这个img,并且进行分区以及格式化。UFEI的分区默认第一分区存放EFI,第二分区存放Linux filesystem
dd if=/dev/zero of=a.img bs=1G count=8
sudo parted a.img mklabel gpt
sudo parted a.img
mkpart ESP fat32 1MiB 500MiB
set 1 esp on
mkpart Linux ext4 500MiB 8GiB
sudo losetup -fP a.img
LOOP_DEV=$(losetup -j a.img | cut -d':' -f1)
sudo mkfs.vfat -F32 ${LOOP_DEV}p1
sudo mkfs.ext4 ${LOOP_DEV}p2
格式化完成后,我们需要将原来test.img里的filesystem拷贝到新的a.img的p2分区里
sudo losetup -fP test.img
sudo mkdir /mnt/{old,new}
sudo mount /dev/loop14p1 /mnt/old # 假设原镜像已挂载为loop14
sudo mount ${LOOP_DEV}p2 /mnt/new # 挂载新根分区
sudo rsync -aAXv /mnt/old/* /mnt/new
sudo umount /mnt/old
之前创建完EFI目录以后,其实该目录还是空的,我们需要制作引导。
sudo mount ${LOOP_DEV}p2 /mnt
mkdir /mnt/boot/efi
sudo mount ${LOOP_DEV}p1 /mnt/boot/efi
for dir in proc sys dev; do
sudo mount --bind /$dir /mnt/$dir
done
sudo chroot /mnt
mount -t proc proc /proc
mount --rbind /sys /sys
mount --rbind /dev /dev
进入封闭的文件系统里以后,我们需要安装grub-efi的工具。
apt install grub-efi-amd64-bin grub-efi-amd64-signed parted acl iptables
grub-install \
--target=x86_64-efi \
--efi-directory=/boot/efi \
--bootloader-id=GRUB \
--removable \
--directory=/usr/lib/grub/x86_64-efi
运行完以后,可以看到boot的efi目录里多了BOOT和GRUB
damn@damn-virtual-machine:/mnt/boot/efi/EFI$ ls
BOOT GRUB
我们还需要拷贝一个文件夹到和一个文件到BOOT和GRUB目录
cd /mnt/boot/grub
ls
fonts grub.cfg grubenv i386-pc locale unicode.pf2 x86_64-efi
cp grub.cfg /mnt/boot/efi/EFI/BOOT
cp grub.cfg /mnt/boot/efi/EFI/GRUB
cp -r x86_64-efi /mnt/boot/efi/EFI/BOOT/
cp -r x86_64-efi /mnt/boot/efi/EFI/GRUB/
update-grub
退出
#在chroot里
umount /proc
umount /dev
umount /sys
exit
#在linux宿主机终端中
umount /mnt/proc
umount /mnt/dev
umount /mnt/sys
umount /mnt/boot/efi
umount /mnt
# 如果一直出现busy,那么可以重启linux系统解决。。。
sudo losetup -d $LOOP_DEV
将a.img写入U盘,用lsblk查看U盘块
lsblk
这里看到我的U盘的标记是/dev/sdb,所以我选择/dev/sdb
sudo dd if=a.img of=/dev/sdb bs=4M status=progress
sync
将制作好的U盘插入PC机,BIOS里选择该U盘启动
启动后输入账号密码,进入U盘的Linux系统。这时候我们需要对PC的硬盘进行分区,换原我们的系统
lsblk
查看到我的PC机的硬盘符为/dev/nvme0n1
sudo parted /dev/nvme0n1
(parted) mklabel gpt
(parted) mkpart ESP fat32 1MiB 500MiB
(parted) set 1 esp on
(parted) mkpart Linux ext4 500MiB 100GiB
退出parted以后,我们用dd命令还原分区
# 我的U盘启动以后,U盘本身的分区是sda
# 拷贝 sda1(EFI 分区)到nvme0n1p1
sudo dd if=/dev/sda1 of=/dev/nvme0n1p1 bs=4M status=progress
# 拷贝 sda2(根分区)
sudo dd if=/dev/sda2 of=/dev/nvme0n1p2 bs=4M status=progress
sync
这里我们还需要修改一部分信息,那就是fstab里的UUID信息,因为磁盘变了,需要修改nvme0n1p2 中的etc/fstab里的磁盘UUID
blkid
/dev/nvme0n1p2 : UUID="f1e07a95-a73e-4b0b-b5e4-b87431cb3366" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="f15e7724-e943-436b-b03b-2e22458ee136"
mount /dev/nvme0n1p2 /mnt
nano /mnt/etc/fstab
修改下面的数据
UUID= / ext4 errors=remount-ro 0 1
# swap was on /dev/sda5 during installation
#UUID=0b5e482e-4657-4c57-ab62-740944d6fa24 none swap sw 0 0
#/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0
修改完以后
UUID=f1e07a95-a73e-4b0b-b5e4-b87431cb3366 / ext4 defaults 0 1
# swap was on /dev/sda5 during installation
#UUID=0b5e482e-4657-4c57-ab62-740944d6fa24 none swap sw 0 0
#/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0
这里修改完,可以直接umount了
umount /mnt
到这里,可以关机拔掉U盘,进行重启,进入BIOS里选择对应的启动项即可,或者如果进不去系统,可以进入UEFI SHELL
fs0:
cd EFI
cd BOOT
./BOOTX64.EFI
#!/bin/bash
echo "Available SSD/HDD"
lsblk -d -o NAME,SIZE,MODEL
read -p "Input the name of SSD/HDD:" target_disk
if [ -z "$target_disk" ]; then
echo "Error: None SSD/HDD"
exit 1
fi
if ! lsblk -d /dev/$target_disk &> /dev/null; then
echo "Error: /dev/$target_disk is not exsited"
exit 1
fi
echo "Creating Partition ..."
sudo parted /dev/$target_disk --script mklabel gpt
sudo parted /dev/$target_disk --script mkpart ESP fat32 1MiB 500MiB
sudo parted /dev/$target_disk --script set 1 esp on
sudo parted /dev/$target_disk --script mkpart Linux ext4 500MiB 95%
sudo parted /dev/$target_disk --script mkpart linux-swap ext4 95% 100%
sudo parted /dev/$target_disk --script set 3 swap on
echo "format swap ..."
sudo mkswap /dev/${target_disk}p3
echo "Copy Data..."
sudo dd if=/dev/sda1 of=/dev/${target_disk}p1 bs=4M status=progress
sudo dd if=/dev/sda2 of=/dev/${target_disk}p2 bs=4M status=progress
sync
echo "Get SSD/HHD UUID..."
uuid=$(sudo blkid -s UUID -o value /dev/${target_disk}p2)
if [ -z "$uuid" ]; then
echo "Error: Can not obtian the uuid of /dev/${target_disk}p2 "
exit 1
fi
echo "Modifying /etc/fstab..."
sudo mount /dev/${target_disk}p2 /mnt
sudo sed -i "s/UUID=[^ ]*/UUID=$uuid/" /mnt/etc/fstab
swap_uuid=$(sudo blkid -s UUID -o value /dev/${target_disk}p3)
if [ -z "$swap_uuid" ]; then
echo "Error: Couldn't get UUID of swap"
exit 1
fi
echo "UUID=$swap_uuid none swap sw 0 0" | sudo tee -a /mnt/etc/fstab
echo "RESUME=UUID=$swap_uuid" | sudo tee /mnt/etc/initramfs-tools/conf.d/resume >/dev/null
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo chroot /mnt update-initramfs -u -k all
sudo umount /mnt/dev
sudo umount /mnt/proc
sudo umount /mnt/sys
sudo umount /mnt
echo "Adjusting Capacity..."
sudo e2fsck -f /dev/${target_disk}p2 # 强制检查文件系统一致性[6,8](@ref)
sudo resize2fs /dev/${target_disk}p2 # 自动扩展到分区最大容量[1,7](@ref)
echo "Done"
read -p "Please press 'Enter' to reboot the system and remove USB devices: " dummy_input
sudo reboot