大约三年前,我购入了人生第一台实体服务器——HP ProLiant MicroServer Gen8。当时的有些选择在现在看来并不是最优的,于是我在 2019 年初对 Gen8 进行了一些软硬件改造。
一、光驱位磁盘问题
Gen8 一共 4 个 3.5 英寸 SATA 硬盘盘位,但总共有 5 个 SATA 接口,第 5 个 SATA 接口在主板上的标记为「SATA - ODD」,原意是接光驱用,但广大 Gen8 用户(甚至包括后来的 Gen10 用户)纷纷选择把这个接口用于接第 5 块硬盘——通常是 2.5 英寸的 SSD。由于 SSD 并不惧怕震动,接好之后往光驱位随便一放即可,当然也可以用双面胶或电工胶带稍微固定一下。
我刚购入 Gen8 的时候,因为种种原因,未使用 SATA 5,而是把 SATA 1 的背板拆了下来,拉到顶上,接了个 2.5 英寸 SSD;从 SATA 2 开始才是接 3.5 英寸 HDD——这相当于浪费了一个 3.5 英寸的盘位。随着数据量的增加,我希望能将 4 个 3.5 英寸盘位全部利用起来,于是就想着把 SSD 移至 SATA 5。
要想让 SSD 工作于 SATA 5,需要解决供电问题。HPE 不知为何,只预留了一个小 4pin 的电源线(常用于软驱),而 SATA 硬盘用的是 15pin 的供电,这两者之间是没有标准转换线的。解决思路有:
- 用两条转换线,先把小 4pin 转成大 4pin,再把大 4pin 转成 15pin;
- 用一转二的 15pin 电源线,把别的 SATA 的供电线分出来给它用。
但大约是有这样需求的用户太多了吧,〇宝上可以买到专门的「Gen8 数据线」,有三个接口,一头接主板上的 SATA 接口,一头接光驱位预留的小 4pin 电源,还有一头直接连到 SATA 的电源/数据接口。
最后成功接上的效果是这样:
简洁又美观。
二、AHCI 模式下的引导问题
Gen8 还有一个怪异点,那就是在 AHCI 模式下无法从任意 SATA 接口引导。
Gen8 是内置一个 B120i RAID 控制器的,但这其实是 Fake RAID,对操作系统不透明,需要加载额外的专有驱动才能使用。此外,为了能让每块硬盘能单独拔下来插到别的电脑上访问其中的内容,我也不会采用 RAID 方案的。从 Gen8 买回来的那天起我就没有启用 RAID 控制器,而是将其配置为 AHCI 模式。
在 AHCI 模式下,Gen8 可以选择从 SATA 控制器引导,但只能从第一个插了盘 SATA 接口引导。比如,四个 3.5 英寸盘位(SATA 1 至 SATA 4)都是空着的情况下,如果 SATA 5 接了一块引导盘,那么 SATA 5 里的系统是可以成功启动的;但如果 SATA 1 至 SATA 4 中的任何一个接口已经接了一块硬盘(不可引导的数据盘),那么 Gen8 就会尝试从那一块硬盘引导——引导失败,并且不再继续尝试后续硬盘。这一怪异点的常见应对方法有:
- 放弃 AHCI,屈服于 B120i 的淫威,配置 Fake RAID,然后就可以从 SATA 5 所在的 RAID 阵列引导了;
- 将系统装在 U 盘或 microSD 卡里(主板上有一个 USB 和一个 microSD 接口),然后在 BIOS 里选择从 USB 引导。
之前我是采取第二种方法。当时我的 Gen8 上装的系统是 VMware ESXi,这一系统只在启动的时候读取文件,之后都是纯内存运行,几乎不再进行写入操作,所以挺适合安装在脆弱的 microSD 卡里的。但我现在换了 Proxmox VE,这是一个基于 Debian Linux 的操作系统,是会有很多日志写入的,装在 U 盘或 microSD 卡里的话,很快就会把 U 盘或 microSD 卡写坏。
然后我有了一个大胆的想法,并实践了一下,发现可行。那就是:用 GRUB 二次引导。
三、使用 GRUB 引导 SATA 5 中的系统
计算机的引导过程,无非就是 BIOS / UEFI 去读取指定硬盘的头部(MBR / GPT),执行引导程序(GRUB、SYSLINUX 等),再由引导程序再去加载操作系统。现在既然 Gen8 不愿意直接从 SATA 5 引导,那么我们就让引导程序去找 SATA 5 好了。
GRUB 是个复杂而又功能强大的引导程序,支持各种文件系统,甚至是 LVM 和 LUKS 等复杂结构,很适合来完成这个「二传」的事情。本文的 GRUB 是指 GRUB 2。
安装 GRUB
取一张空白 microSD 卡或一只空白的 U 盘(我直接拿之前装 ESXi 的那张了),插到任意一台 GNU/Linux 机器上(虚拟机应该也行),开始操作。
# 执行以下命令前,请先使用你最爱的包管理器安装 gdisk 和 grub
# 擦除已有 MBR / GPT,请先用 lsblk 确认 microSD 卡的名字,此处为 /dev/sdb
$ sudo sgdisk -Z /dev/sdb
# 新建两个分区,一个 2 MiB 的 BIOS boot partition,一个 512 MiB 的 EFI System
$ sudo sgdisk -n 1:0:+2M -t 1:ef02 -n 2:0:+512M -t 2:ef00 /dev/sdb
# 格式化 EFI 分区
$ sudo mkfs.vfat /dev/sdb2
# 挂载 EFI 分区
$ sudo mount /dev/sdb2 /mnt
# 新建 boot 目录(用于安装 GRUB)
$ sudo mkdir /mnt/boot
# 将 GRUB 安装到 microSD 卡里
$ sudo grub-install --boot-directory /mnt/boot /dev/sdb
至此 GRUB 已经被安装到 microSD 里了。但是我们还没有配置文件。GRUB 本身提供了 grub-mkconfig
工具可以用来生成一个适用于当前系统的配置文件,但这并不是我们想要的,所以我们需要手写一个。
配置 GRUB
根据你安装 GRUB 时的发行版,GRUB 可能被安装到了 /mnt/boot/grub
或是 /mnt/boot/grub2
目录里,这不重要;其配置文件 grub.cfg
就在这个目录里。使用你最喜爱的编辑器打开 grub.cfg
文件(新文件),参考 GRUB 文档,增加类似这样的条目:
set timeout=5
menuentry 'Load Proxmox VE grub.cfg' {
insmod part_gpt
insmod lvm
insmod ext2
set root='lvmid/jfwkcN-crbm-WWJc-jpWT-0Tif-mpIW-RIPmN7/OK06r0-BiRx-6a3R-NnZZ-dbZC-0Urx-w0uEPe'
configfile /boot/grub/grub.cfg
}
其中 insmod
的作用是加载必要的模块(比如要读取 LVM 卷里的数据,就要加载 lvm 模块);set root
是指定根目录(/
)所在的分区/卷(相当于挂载);最后 configfile
指示 GRUB 去加载根目录里另一个 grub.cfg(属于 Proxmox VE)配置。
更新:应读者询问补充说明:上述配置中 root=
后面的 lvmid 可通过 lvdisplay
命令获取。
完整的引导过程是这样:
- Gen8 的 BIOS 试图从 microSD 引导,成功执行 microSD 上的引导程序(GRUB);
- GRUB 根据 microSD 上
grub.cfg
文件中的信息,凭借 LVM UUID 定位到 SATA 5 上的 Proxmox VE 分区,并读取其中的grub.cfg
文件; - GRUB 根据新的配置文件重新加载自身,并根据新文件中的配置加载操作系统(Proxmox VE)。
这一过程中涉及到了两个引导程序,都是 GRUB。但第二个引导程序可以是别的,比如对于 Windows,可以使用 ntldr /bootmgr
来执行 Windows 的引导程序;你也可以使用 chainloader +1
来将控制权交给任意其他引导器。
上面的例子中使用了 LVM ID 来定位第二个引导程序所在的分区/卷,你也可以用 search
命令,凭借文件系统的 UUID 或卷标来定位(这些信息可以用 lsblk
或 grub-probe
找到)。比如这是一个引导安装在 MBR 分区里的 Windows 10 的例子(真的有人在 Gen8 上安装 Windows 10 吗?):
menuentry "Windows 10" {
insmod part_msdos
insmod ntfs
insmod ntldr
search --fs-uuid --set=root 2ABF87DC395CFC02
ntldr /bootmgr
}
更多的例子可以参考 ArchWiki 和 Gentoo Wiki。
引导!
将制作好的 microSD 插入 Gen8 主板,在 BIOS 中选择从「USB Key」启动,重启。在 POST 之后,可以看到 microSD 里的 GRUB 的菜单,有且只有一条选择,那就是我们刚才手写的加载另一个引导程序的条目。若不做任何操作,则在 5 秒后(由 set timeout
决定)自动选择,然后你就能看到第二个引导程序的界面了。
在 microSD 制作完成之后,就不会再有写入了,且 microSD 上的 GRUB 也只在 Gen8 启动时读取一次,进入操作系统之后就不再读取(你甚至可以把它拔下来——当然记得下次启动的时候插回去),就算是脆弱的 microSD 卡,也应该能用很久。