0%

Linux虚拟镜像创建分区和Grub2安装

1. 创建虚拟磁盘

1
dd if=/dev/zero of=15g.img bs=1M count=15360 # 15GB

2. 挂载img

1
2
sudo losetup -l # 查看当前loop设备
sudo losetup /dev/loop0 15g.img # 挂在到空闲的loop0上

3. img分区

通过fdisk对img分区
执行:

1
sudo fdisk /dev/loop0

进入提示:

1
2
3
4
5
6
7
8
欢迎使用 fdisk (util-linux 2.34)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

设备不包含可识别的分区表。
创建了一个磁盘标识符为 0x7accf69c 的新 DOS 磁盘标签。

命令(输入 m 获取帮助):

输入m,查看帮助

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
命令(输入 m 获取帮助): m

帮助:

DOS (MBR)
a 开关 可启动 标志
b 编辑嵌套的 BSD 磁盘标签
c 开关 dos 兼容性标志

常规
d 删除分区
F 列出未分区的空闲区
l 列出已知分区类型
n 添加新分区
p 打印分区表
t 更改分区类型
v 检查分区表
i 打印某个分区的相关信息

杂项
m 打印此菜单
u 更改 显示/记录 单位
x 更多功能(仅限专业人员)

脚本
I 从 sfdisk 脚本文件加载磁盘布局
O 将磁盘布局转储为 sfdisk 脚本文件

保存并退出
w 将分区表写入磁盘并退出
q 退出而不保存更改

新建空磁盘标签
g 新建一份 GPT 分区表
G 新建一份空 GPT (IRIX) 分区表
o 新建一份的空 DOS 分区表
s 新建一份空 Sun 分区表


命令(输入 m 获取帮助):

我们主要用到的有:

  • n   添加新分区
  • t   更改分区类型
  • a   开关 可启动 标志
  • w   将分区表写入磁盘并退出
  • q   退出而不保存更改

下面首先来分区,这里主要分为3个区,boot,rootfs和swap分区

  1. boot分区分200M,
  2. swap分1G
  3. 其余分到rootfs

3.1 Boot分区

1
2
3
4
5
6
7
8
9
10
命令(输入 m 获取帮助): n
分区类型
p 主分区 (0个主分区,0个扩展分区,4空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (1-4, 默认 1):
第一个扇区 (2048-31457279, 默认 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-31457279, 默认 31457279): +200M

创建了一个新分区 1,类型为“Linux”,大小为 200 MiB。

一张硬盘上,主分区最多只能有4个,加入4个主分区未将磁盘使用完,剩下的空间是无法在分配的,也就是无法使用。如果一张硬盘上想有个多分区,做多3个主分区,至少一个扩展分区,剩下的为逻辑分区。在有逻辑分区的情况下,必须有一个以上的扩展分区。逻辑分区没有数量限制。
一张硬盘上,分区表一般位于硬盘某柱面的0磁头1扇区。而第1个分区表(也即主分区表)总是位于(0柱面,0磁头,1扇区),剩余的分区表位置可以由主分区表依次推导出来。硬盘第一个扇区(512字节)坏死了,那么这个硬盘就没法用了。

t 可修改分区类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
命令(输入 m 获取帮助): t
已选择分区 1
Hex 代码(输入 L 列出所有代码): L

0 空 24 NEC DOS 81 Minix / 旧 Linu bf Solaris
1 FAT12 27 隐藏的 NTFS Win 82 Linux swap / So c1 DRDOS/sec (FAT-
2 XENIX root 39 Plan 9 83 Linux c4 DRDOS/sec (FAT-
3 XENIX usr 3c PartitionMagic 84 OS/2 隐藏 或 In c6 DRDOS/sec (FAT-
4 FAT16 <32M 40 Venix 80286 85 Linux 扩展 c7 Syrinx
5 扩展 41 PPC PReP Boot 86 NTFS 卷集 da 非文件系统数据
6 FAT16 42 SFS 87 NTFS 卷集 db CP/M / CTOS / .
7 HPFS/NTFS/exFAT 4d QNX4.x 88 Linux 纯文本 de Dell 工具
8 AIX 4e QNX4.x 第2部分 8e Linux LVM df BootIt
9 AIX 可启动 4f QNX4.x 第3部分 93 Amoeba e1 DOS 访问
a OS/2 启动管理器 50 OnTrack DM 94 Amoeba BBT e3 DOS R/O
b W95 FAT32 51 OnTrack DM6 Aux 9f BSD/OS e4 SpeedStor
c W95 FAT32 (LBA) 52 CP/M a0 IBM Thinkpad 休 ea Rufus 对齐
e W95 FAT16 (LBA) 53 OnTrack DM6 Aux a5 FreeBSD eb BeOS fs
f W95 扩展 (LBA) 54 OnTrackDM6 a6 OpenBSD ee GPT
10 OPUS 55 EZ-Drive a7 NeXTSTEP ef EFI (FAT-12/16/
11 隐藏的 FAT12 56 Golden Bow a8 Darwin UFS f0 Linux/PA-RISC
12 Compaq 诊断 5c Priam Edisk a9 NetBSD f1 SpeedStor
14 隐藏的 FAT16 <3 61 SpeedStor ab Darwin 启动 f4 SpeedStor
16 隐藏的 FAT16 63 GNU HURD 或 Sys af HFS / HFS+ f2 DOS 次要
17 隐藏的 HPFS/NTF 64 Novell Netware b7 BSDI fs fb VMware VMFS
18 AST 智能睡眠 65 Novell Netware b8 BSDI swap fc VMware VMKCORE
1b 隐藏的 W95 FAT3 70 DiskSecure 多启 bb Boot Wizard 隐 fd Linux raid 自动
1c 隐藏的 W95 FAT3 75 PC/IX bc Acronis FAT32 L fe LANstep
1e 隐藏的 W95 FAT1 80 旧 Minix be Solaris 启动 ff BBT
Hex 代码(输入 L 列出所有代码): 83
已将分区“Linux”的类型更改为“Linux”。

3.2 rootfs分区

1
2
3
4
5
6
7
8
9
10
命令(输入 m 获取帮助): n
分区类型
p 主分区 (1个主分区,0个扩展分区,3空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (2-4, 默认 2):
第一个扇区 (411648-31457279, 默认 411648):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (411648-31457279, 默认 31457279): +14136M

创建了一个新分区 2,类型为“Linux”,大小为 13.8 GiB。

3.3 swap分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
命令(输入 m 获取帮助): n
分区类型
p 主分区 (2个主分区,0个扩展分区,2空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (3,4, 默认 3):
第一个扇区 (29362176-31457279, 默认 29362176):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (29362176-31457279, 默认 31457279):

创建了一个新分区 3,类型为“Linux”,大小为 1023 MiB。

命令(输入 m 获取帮助): t
分区号 (1-3, 默认 3): 3
Hex 代码(输入 L 列出所有代码): 82

已将分区“Linux”的类型更改为“Linux swap / Solaris”。

3.4 设置Boot分区可以引导标记

磁盘开头的446字节内容特指为“主引导记录”(MBR),其后是4个16字节的“磁盘分区表”(DPT),以及2字节的结束标志(55AA)。446 + 4*16 + 2 = 512字节。
可引导标记就是此分区的第一个扇区最后2个字节为55AA。

1
2
3
4
命令(输入 m 获取帮助): a
分区号 (1-3, 默认 3): 1

分区 1 的 可启动 标志已启用。

a 设置可引导标记,选择分区1。 

3.5 保存分区记录

1
2
3
4
5
6
命令(输入 m 获取帮助): w
分区表已调整。
将调用 ioctl() 来重新读分区表。
重新读取分区表失败。: 无效的参数

内核仍在使用旧分区表。新分区表将在下次重启或运行 partprobe(8) 或 kpartx(8) 后生效。

操作完后一定记得输入 w 保存。 重新读取分区表失败 可以忽略,此时已经成功了。

3.6 卸载设备

1
sudo losetup -d /dev/loop0 # 卸载loop设备

3.7 查看img分区情况

1
2
3
4
5
6
7
8
9
10
11
12
13
fdisk -l 15g.img     

Disk 15g.img:15 GiB,16106127360 字节,31457280 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xc71ed2c6

设备 启动 起点 末尾 扇区 大小 Id 类型
15g.img1 * 2048 411647 409600 200M 83 Linux
15g.img2 411648 29362175 28950528 13.8G 83 Linux
15g.img3 29362176 31457279 2095104 1023M 82 Linux swap / Solaris

4. losetup挂载分区

4.1 将分区挂在到loop设备

1
2
3
4
5
# -o (起始扇区 * 扇区大小)--sizelimit (扇区数量 * 扇区大小) 字节
# 2048 x 512 = 1048576 409600 x 512 = 209715200
sudo losetup -f -o 1048576 --sizelimit 209715200 15g.img
sudo losetup -f -o 210763776 --sizelimit 14822670336 15g.img
sudo losetup -f -o 15033434112 --sizelimit 1072693248 15g.img

由于 15g.img 中包含3个分区,如果使用 losetup 挂载,需要计算每个分区的其实位置和大小。
起始位置和偏移通过 3.7中的信息可以查看到。
-o 起点512
--sizelimit 扇区
512

4.2 查看挂载情况

1
2
3
4
5
6
sudo losetup -l

NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop1 14822670336 210763776 0 0 /home/zauther/zos/product/zos15g.img 0 512
/dev/loop2 1072693248 15033434112 0 0 /home/zauther/zos/product/zos15g.img 0 512
/dev/loop0 209715200 1048576 0 0 /home/zauther/zos/product/zos15g.img 0 512

/dev/loop0  对应boot分区
/dev/loop1 对应rootfs分区
/dev/loop2  对应swap分区

4.3 格式化分区

1
2
3
sudo mkfs.ext4 /dev/loop0
sudo mkfs.ext4 /dev/loop1
sudo mkswap /dev/loop2

4.4 挂载到mnt

1
2
3
4
sudo mkdir /mnt/boot
sudo mkdir /mnt/rootfs
sudo mount /dev/loop0 /mnt/boot
sudo mount /dev/loop1 /mnt/rootfs

4.5 查看挂载情况

1
2
3
4
5
df -h

文件系统 容量 已用 可用 已用% 挂载点
/dev/loop0 178M 216K 164M 1% /mnt/boot
/dev/loop1 14G 41M 13G 1% /mnt/rootfs

5 kpartx 挂载分区

通过losetup挂载需要手动计算位置,如果虚假镜像中包含分区表,可以通过kpartx一次性挂载

1
2
3
4
5
kpartx -av 15g.img 

add map loop0p1 (253:2): 0 409600 linear 7:2 2048
add map loop0p2 (253:3): 0 28950528 linear 7:2 411648
add map loop0p3 (253:4): 0 2095104 linear 7:2 29362176

-a 添加镜像
-v verbos信息打印
kpartx会将 15g.img 挂载到 /dev/loop0 然后映射到 /dev/mapper 中:

1
2
3
ls /dev/mapper/       

control loop0p1 loop0p2 loop0p3

可参考4.4 中,将loop0p1  loop0p2  loop0p3分别挂载到/mnt中:

1
sudo mount  /dev/mapper/loop0p1 /mnt/boot

6 安装Grub2到设备

6.1 安装grub

1
2
sudo apt update
sudo apt install grub2

6.2 安装Grub2到设备

强制安装到 /dev/mapper/loop0p1 即boot分区:

1
grub-install --boot-directory=/mnt/boot --force --allow-floppy /dev/mapper/loop0p1

--boot-directory boot分区中的目录位置,需要在boot分区中新建以下文件夹:
在执行完 sudo mount  /dev/mapper/loop0p1 /mnt/boot 后:

1
2
3
4
cd /mnt/boot
sudo mkdir -p mnt/boot
cd mnt/boot
sudo mkdir grub

此时路径为 /mnt/boot/mnt/boot 。
当然也可以再前面直接挂载 sudo mount  /dev/mapper/loop0p1 /mnt

6.3 测试

1
qemu-system-x86_64 -nographic -drive format=raw,file=15g.img

7 通过Docker安装Grub2

7.1 安装docker

1
2
3
4
5
6
7
8
sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \
$(lsb_release -cs) \
stable"
sudo apt-get update
sudo apt-get install docker-ce

7.2 添加dockerhub加速镜像

1
2
3
sudo vim /etc/docker/daemon.json
sudo systemctl daemon-reload
sudo systemctl restart docker

/etc/docker/daemon.json

1
2
3
4
5
6
7
8
9
10
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://registry.docker-cn.com",
"https://reg-mirror.qiniu.com",
"https://dockerhub.azk8s.cn",
"https://docker.mirrors.ustc.edu.cn"
]
}

7.3 拉取Ubuntu镜像并执行

1
2
sudo docker pull ubuntu
sudo docker run --rm -it -v ~/testgrub:/root/testgrub ubuntu

--rm 运行完退出容器后,自动销毁并删除镜像
-it 以bash交互的形式运行容器
-v ~/testgrub:/root/testgrub  本地卷:容器内卷 映射
在容器内按第6节中的操作,会发现loop设备无法使用。

7.4 添加设备映射

1
2
3
sudo vim /etc/docker/daemon.json
sudo systemctl daemon-reload
sudo systemctl restart docker

添加设备映射并重启docker
/etc/docker/daemon.json

1
2
3
4
5
6
7
8
9
10
11
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://registry.docker-cn.com",
"https://reg-mirror.qiniu.com",
"https://dockerhub.azk8s.cn",
"https://docker.mirrors.ustc.edu.cn"
],
"storage-driver": "devicemapper"
}

8 卸载设备

在安装完grub2后,卸载设备

1
2
3
4
sudo umount /mnt/boot/ 

sudo losetup -d /dev/loop0 # loop加载时
sudo kpartx -dv 15g.img # kpartx加载时

kpartx:
-d 卸载镜像,会同时卸载/dev/mapper/loop0p*/dev/loop0