在 如何構建一台網路引導伺服器(一) 中,我們提供了一個極簡的 iPXE 引導腳本來引導你的網路引導鏡像

。許多用戶除了使用網路引導鏡像外,可能在機器本地也有一個操作系統。但是使用常見的工作站的 BIOS 去切換引導載入器是很笨拙的。在本系列文件的第三部分,我們將向你展示如何設置一個更複雜的 iPXE 配置。它將允許終端用戶以更容易的方式去選擇引導哪個操作系統。它也可以配置為讓系統管理員從一台中央伺服器來統一管理引導菜單。

一個互動式 iPXE 引導菜單

下面這些命令重定義了網路引導鏡像的 boot.cfg 來作為一個互動式的 iPXE 引導菜單,並使用了一個 5 秒倒計時的定時器:

$ MY_FVER=29
$ MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)
$ MY_DNS1=192.0.2.91
$ MY_DNS2=192.0.2.92
$ MY_NAME=server-01.example.edu
$ MY_EMAN=$(echo $MY_NAME | tr . "
" | tac | tr "
" . | cut -b -${#MY_NAME})
$ MY_ADDR=$(host -t A $MY_NAME | awk {print $4})
$ cat << END > $HOME/esp/linux/boot.cfg
#!ipxe

set timeout 5000

:menu
menu iPXE Boot Menu
item --key 1 lcl 1. Microsoft Windows 10
item --key 2 f$MY_FVER 2. RedHat Fedora $MY_FVER
choose --timeout ${timeout} --default lcl selected || goto shell
set timeout 0
goto ${selected}

:failed
echo boot failed, dropping to shell...
goto shell

:shell
echo type exit to get the back to the menu
set timeout 0
shell
goto menu

:lcl
exit

:f$MY_FVER
kernel --name kernel.efi ${prefix}/vmlinuz-$MY_KRNL initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=$MY_DNS1 nameserver=$MY_DNS2 root=/dev/disk/by-path/ip-$MY_ADDR:3260-iscsi-iqn.$MY_EMAN:fc$MY_FVER-lun-1 netroot=iscsi:$MY_ADDR::::iqn.$MY_EMAN:fc$MY_FVER console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-$MY_KRNL.img
boot || goto failed
END

上述菜單有五個節:

  • menu 定義了顯示在屏幕上的實際菜單內容。
  • failed 提示用戶發生了錯誤,並將用戶帶到 shell 以錯誤錯誤。
  • shell 提供了互動式命令提示符。你可以在引導菜單出現時按下 Esc 鍵進入,或者是 boot命令失敗時也會進入到命令提示符。
  • lcl 包含一個提供給 iPXE 退出的簡單命令,以及返還控制權給 BIOS。在 iPXE 之後,無論你希望預設引導的設備(即:工作站的本地硬體)是什麼,都必須在你的工作站的 BIOS 中正確地作為下一個引導設備列出來。
  • f29 包含前面文章提到同一個網路引導代碼,但使用最終的退出代碼來替換掉 goto failed

從你的 $HOME/esp/linux 目錄中複製更新後的 boot.cfg 到所有客戶端系統的 ESP 中。如果一切順利,你應該會看到類似下面圖片的結果:

一個伺服器託管的引導菜單

你可以添加到網路引導伺服器的另一個特性是,能夠從一台中央位置去管理所有客戶端的引導菜單。這個特性尤其適用於批量安裝(升級)一個新版本的操作系統。在你將新內核和新的 initramfs 複製到所有客戶端的 ESP 之後,這個特性可以讓你執行一種 原子事務 去切換所有客戶端到新操作系統。

安裝 Mojolicious:

$ sudo -i
# dnf install -y perl-Mojolicious

定義 「bootmenu」 應用程序:

# mkdir /opt/bootmenu
# cat << END > /opt/bootmenu/bootmenu.pl
#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojolicious::Plugins;

plugin Config;

get /menu;

app->start;
END
# chmod 755 /opt/bootmenu/bootmenu.pl

為 「bootmenu」 應用程序定義配置文件:

# cat << END > /opt/bootmenu/bootmenu.conf
{
hypnotoad => {
listen => [http://*:80],
pid_file => /run/bootmenu/bootmenu.pid,
}
}
END

這是一個非常簡單的 Mojolicious 應用程序,它監聽 80 埠,並且只回應對 /menu 的請求。如果你想快速了解 Mojolicious 能做什麼,運行 man Mojolicious::Guides::Growing 去查看手冊。按 Q 鍵退出手冊。

boot.cfg 移到我們的網路引導應用程序中作為一個名為 menu.html.ep 的模板:

# mkdir /opt/bootmenu/templates
# mv $HOME/esp/linux/boot.cfg /opt/bootmenu/templates/menu.html.ep

定義一個 systemd 服務去管理引導菜單應用程序:

# cat << END > /etc/systemd/system/bootmenu.service
[Unit]
Description=Serves iPXE Menus over HTTP
After=network-online.target

[Service]
Type=forking
DynamicUser=true
RuntimeDirectory=bootmenu
PIDFile=/run/bootmenu/bootmenu.pid
ExecStart=/usr/bin/hypnotoad /opt/bootmenu/bootmenu.pl
ExecReload=/usr/bin/hypnotoad /opt/bootmenu/bootmenu.pl
AmbientCapabilities=CAP_NET_BIND_SERVICE
KillMode=process

[Install]
WantedBy=multi-user.target
END

在本地防火牆中為 HTTP 服務添加一個例外規則,並啟動 bootmenu 服務:

# firewall-cmd --add-service http
# firewall-cmd --runtime-to-permanent
# systemctl enable bootmenu.service
# systemctl start bootmenu.service

wget 測試它:

$ sudo dnf install -y wget
$ MY_BOOTMENU_SERVER=server-01.example.edu
$ wget -q -O - http://$MY_BOOTMENU_SERVER/menu

以上的命令應該會輸出類似下面的內容:

#!ipxe

set timeout 5000

:menu
menu iPXE Boot Menu
item --key 1 lcl 1. Microsoft Windows 10
item --key 2 f29 2. RedHat Fedora 29
choose --timeout ${timeout} --default lcl selected || goto shell
set timeout 0
goto ${selected}

:failed
echo boot failed, dropping to shell...
goto shell

:shell
echo type exit to get the back to the menu
set timeout 0
shell
goto menu

:lcl
exit

:f29
kernel --name kernel.efi ${prefix}/vmlinuz-4.19.4-300.fc29.x86_64 initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=192.0.2.91 nameserver=192.0.2.92 root=/dev/disk/by-path/ip-192.0.2.158:3260-iscsi-iqn.edu.example.server-01:fc29-lun-1 netroot=iscsi:192.0.2.158::::iqn.edu.example.server-01:fc29 console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-4.19.4-300.fc29.x86_64.img
boot || goto failed

現在,引導菜單伺服器已經正常工作了,重新構建 ipxe.efi 引導載入器,使用一個初始化腳本指向它。

第一步,先更新我們在本系列文章的第一部分中創建的 init.ipxe 腳本:

$ MY_BOOTMENU_SERVER=server-01.example.edu
$ cat << END > $HOME/ipxe/init.ipxe
#!ipxe

dhcp || exit
set prefix file:///linux
chain http://$MY_BOOTMENU_SERVER/menu || exit
END

現在,重新構建引導載入器:

$ cd $HOME/ipxe/src
$ make clean
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe

將更新後的引導載入器複製到你的 ESP 中:

$ cp $HOME/ipxe/src/bin-x86_64-efi/ipxe.efi $HOME/esp/efi/boot/bootx64.efi

將更新後的引導載入器複製到所有的客戶端中之後,以後更新引導菜單只需要簡單地編輯 /opt/bootmenu/templates/menu.html.ep 文件,然後再運行如下命令:

$ sudo systemctl restart bootmenu.service

做一步的改變

如果引導菜單伺服器工作正常,在你的客戶端系統上的 boot.cfg 文件將更長。

比如,重新添加 Fedora 28 鏡像到引導菜單中:

$ sudo -i
# MY_FVER=28
# MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)
# MY_DNS1=192.0.2.91
# MY_DNS2=192.0.2.92
# MY_NAME=$(</etc/hostname)
# MY_EMAN=$(echo $MY_NAME | tr . "
" | tac | tr "
" . | cut -b -${#MY_NAME})
# MY_ADDR=$(host -t A $MY_NAME | awk {print $4})
# cat << END >> /opt/bootmenu/templates/menu.html.ep

:f$MY_FVER
kernel --name kernel.efi ${prefix}/vmlinuz-$MY_KRNL initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=$MY_DNS1 nameserver=$MY_DNS2 root=/dev/disk/by-path/ip-$MY_ADDR:3260-iscsi-iqn.$MY_EMAN:fc$MY_FVER-lun-1 netroot=iscsi:$MY_ADDR::::iqn.$MY_EMAN:fc$MY_FVER console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-$MY_KRNL.img
boot || goto failed
END
# sed -i "/item --key 2/a item --key 3 f$MY_FVER 3. RedHat Fedora $MY_FVER" /opt/bootmenu/templates/menu.html.ep
# systemctl restart bootmenu.service

如果一切順利,你的客戶端下次引導時,應該看到如下圖所示的結果:


via: fedoramagazine.org/how-

作者:Gregory Bartholomew 選題:lujun9972 譯者:qhwdw 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


推薦閱讀:
相关文章