## 19.3 Boot Loader: Grub2
在看完了前面的整個開機流程,以及核心模塊的整理之后,你應該會發現到一件事情,那就是“ boot loader 是載入核心的重要工具”啊!沒有 boot loader 的話,那么 kernel 根本就沒有辦法被系統載入的呢!所以,下面我們會先談一談 boot loader 的功能,然后再講一講現階段 Linux 里頭最主流的 grub2 這個 boot loader 吧!
另外,你也得要知道,目前新版的 CentOS 7.x 已經將沿用多年的 grub 換成了 grub2 了!這個 grub2 版本在設置與安裝上面跟之前的 grub 有點不那么相同, 所以,在后續的章節中,得要了解一下新的 grub2 的設置方式才行喔!如果你是新接觸者,那沒關系~直接看就 OK 了!
### 19.3.1 boot loader 的兩個 stage
我們在第一小節開機流程的地方曾經講過,在 BIOS 讀完信息后,接下來就是會[到第一個開機設備的 MBR 去讀取 boot loader](../Text/index.html#process_2) 了。這個 boot loader 可以具有菜單功能、直接載入核心文件以及控制權移交的功能等, 系統必須要有 loader 才有辦法載入該操作系統的核心就是了。但是我們都知道, MBR 是整個硬盤的第一個 sector 內的一個區塊,充其量整個大小也才 446 Bytes 而已。即使是 GPT 也沒有很大的扇區來儲存 loader 的數據。 我們的 loader 功能這么強,光是程序碼與設置數據不可能只占這么一點點的容量吧?那如何安裝?
為了解決這個問題,所以 Linux 將 boot loader 的程序碼執行與設置值載入分成兩個階段 (stage) 來執行:
* Stage 1:執行 boot loader 主程序:
第一階段為執行 boot loader 的主程序,這個主程序必須要被安裝在開機區,亦即是 MBR 或者是 boot sector 。但如前所述,因為 MBR 實在太小了,所以,MBR 或 boot sector 通常僅安裝 boot loader 的最小主程序, 并沒有安裝 loader 的相關配置文件;
* Stage 2:主程序載入配置文件:
第二階段為通過 boot loader 載入所有配置文件與相關的環境參數文件 (包括文件系統定義與主要配置文件 grub.cfg), 一般來說,配置文件都在 /boot 下面。
那么這些配置文件是放在哪里啊?這些與 grub2 有關的文件都放置到 /boot/grub2 中,那我們就來看看有哪些文件吧!
```
[root@study ~]# ls -l /boot/grub2
-rw-r--r--. device.map <==grub2 的設備對應檔(下面會談到)
drwxr-xr-x. fonts <==開機過程中的畫面會使用到的字體數據
-rw-r--r--. grub.cfg <==grub2 的主配置文件!相當重要!
-rw-r--r--. grubenv <==一些環境區塊的符號
drwxr-xr-x. i386-pc <==針對一般 x86 PC 所需要的 grub2 的相關模塊
drwxr-xr-x. locale <==就是語系相關的數據啰
drwxr-xr-x. themes <==一些開機主題畫面數據
[root@study ~]# ls -l /boot/grub2/i386-pc
-rw-r--r--. acpi.mod <==電源管理有關的模塊
-rw-r--r--. ata.mod <==磁盤有關的模塊
-rw-r--r--. chain.mod <==進行 loader 控制權移交的相關模塊
-rw-r--r--. command.lst <==一些指令相關性的列表
-rw-r--r--. efiemu32.o <==下面幾個則是與 uefi BIOS 相關的模塊
-rw-r--r--. efiemu64.o
-rw-r--r--. efiemu.mod
-rw-r--r--. ext2.mod <==EXT 文件系統家族相關模塊
-rw-r--r--. fat.mod <==FAT 文件系統模塊
-rw-r--r--. gcry_sha256.mod <==常見的加密模塊
-rw-r--r--. gcry_sha512.mod
-rw-r--r--. iso9660.mod <==光盤文件系統模塊
-rw-r--r--. lvm.mod <==LVM 文件系統模塊
-rw-r--r--. mdraid09.mod <==軟件磁盤陣列模塊
-rw-r--r--. minix.mod <==MINIX 相關文件系統模塊
-rw-r--r--. msdospart.mod <==一般 MBR 分區表
-rw-r--r--. part_gpt.mod <==GPT 分區表
-rw-r--r--. part_msdos.mod <==MBR 分區表
-rw-r--r--. scsi.mod <==SCSI 相關模塊
-rw-r--r--. usb_keyboard.mod <==下面兩個為 USB 相關模塊
-rw-r--r--. usb.mod
-rw-r--r--. vga.mod <==VGA 顯卡相關模塊
-rw-r--r--. xfs.mod <==XFS 文件系統模塊
# 鳥哥這里只拿一些模塊作說明,沒有全部的文件都列上來喔!
```
從上面的說明你可以知道 /boot/grub2/ 目錄下最重要的就是配置文件 (grub2.cfg) 以及各種文件系統的定義! 我們的 loader 讀取了這種文件系統定義數據后,就能夠認識文件系統并讀取在該文件系統內的核心文件啰。
所以從上面的文件來看, grub2 認識的文件系統與磁盤分區格式真的非常多喔!正因為如此,所以 grub2 才會取代 Lilo / grub 這個老牌的 boot loader 嘛!好了,接下來就來瞧瞧配置文件內有啥設置值吧!
### 19.3.2 grub2 的配置文件 /boot/grub2/grub.cfg 初探
grub2 的優點挺多的,包括有:
* 認識與支持較多的文件系統,并且可以使用 grub2 的主程序直接在文件系統中搜尋核心文件名;
* 開機的時候,可以“自行編輯與修改開機設置項目”,類似 bash 的指令模式;
* 可以動態搜尋配置文件,而不需要在修改配置文件后重新安裝 grub2 。亦即是我們只要修改完 /boot/grub2/grub.cfg 里頭的設置后,下次開機就生效了!
上面第三點其實就是 Stage 1, Stage 2 分別安裝在 MBR (主程序) 與文件系統當中 (配置文件與定義文件) 的原因啦! 好了,接下來,讓我們好好了解一下 grub2 的配置文件: /boot/grub2/grub.cfg 這玩意兒吧!
* 磁盤與分區在 grub2 中的代號
安裝在 MBR 的 grub2 主程序,最重要的任務之一就是從磁盤當中載入核心文件, 以讓核心能夠順利的驅動整個系統的硬件。所以啰, grub2 必須要認識硬盤才行啊!那么 grub2 到底是如何認識硬盤的呢? 嘿嘿! grub2 對硬盤的代號設置與傳統的 Linux 磁盤代號可完全是不同的!grub2 對硬盤的識別使用的是如下的代號:
```
(hd0,1) # 一般的默認語法,由 grub2 自動判斷分區格式
(hd0,msdos1) # 此磁盤的分區為傳統的 MBR 模式
(hd0,gpt1) # 此磁盤的分區為 GPT 模式
```
夠神了吧?跟 /dev/sda1 風馬牛不相干~怎么辦啊?其實只要注意幾個東西即可,那就是:
* 硬盤代號以小括號 ( ) 包起來;
* 硬盤以 hd 表示,后面會接一組數字;
* 以“搜尋順序”做為硬盤的編號!(這個重要!)
* 第一個搜尋到的硬盤為 0 號,第二個為 1 號,以此類推;
* 每顆硬盤的第一個 partition 代號為 1 ,依序類推。
所以說,第一顆“搜尋到的硬盤”代號為:“(hd0)”,而該顆硬盤的第一號分區為“(hd0,1)”,這樣說了解了吧? 另外,為了區分不同的分區格式,因此磁盤后面的分區號碼可以使用類似 msdos1 與 gpt1 的方式來調整! 最終要記得的是,磁盤的號碼是由 0 開始編號,分區的號碼則與 Linux 一樣,是由 1 號開始編號!兩者不同喔!

**Tips** 跟舊版的 grub 有點不一樣,因為舊版的 grub 不論磁盤還是分區的起始號碼都是 0 號,而 grub2 在分區的部份是以 1 號開始編喔! 此外,由于 BIOS 可以調整磁盤的開機順序,因此上述的磁盤對應的 (hdN) 那個號碼 N 是可能會變動的喔!這要先有概念才行!
所以說,整個硬盤代號為:
| 硬盤搜尋順序 | 在 Grub2 當中的代號 |
| --- | --- |
| 第一顆(MBR) | (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3).... |
| 第二顆(GPT) | (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3).... |
| 第三顆 | (hd2) (hd2,1) (hd2,2) (hd2,3).... |
這樣應該比較好看出來了吧?第一顆硬盤的 MBR 安裝處的硬盤代號就是“(hd0)”, 而第一顆硬盤的第一個分區的 boot sector 代號就是“(hd0,msdos1)”第一顆硬盤的第一個邏輯分區的 boot sector 代號為“(hd0,msdos5)”瞭了吧!
例題:假設你的系統僅有一顆 SATA 硬盤,請說明該硬盤的第一個邏輯分區在 Linux 與 grub2 當中的文件名與代號:答:因為是 SATA 磁盤,加上使用邏輯分區,因此 Linux 當中的文件名為 /dev/sda5 才對 (1~4 保留給 primary 與 extended 使用)。 至于 grub2 當中的磁盤代號則由于僅有一顆磁盤,因此代號會是“ (hd0,msdos5) ”或簡易的寫法“ (hd0,5) ”才對。
* /boot/grub2/grub.cfg 配置文件(重點在了解,不要隨便改!):
了解了 grub2 當中最麻煩的硬盤代號后,接下來,我們就可以瞧一瞧配置文件的內容了。先看一下鳥哥的 CentOS 內的 /boot/grub2/grub.cfg 好了:
```
[root@study ~]# vim /boot/grub2/grub.cfg
# 開始是 /etc/grub.d/00_header 這個腳本執行的結果展示,主要與基礎設置與環境有關
### BEGIN /etc/grub.d/00_header ###
set pager=1
if [ -s $prefix/grubenv ]; then
load_env
fi
.....(中間省略).....
if [ x$feature_timeout_style = xy ] ; then
set timeout_style=menu
set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
set timeout=5
fi
### END /etc/grub.d/00_header ###
# 開始執行 /etc/grub.d/10_linux,主要針對實際的 Linux 核心文件的開機環境
### BEGIN /etc/grub.d/10_linux ###
menuentry 'CentOS Linux 7 (Core), with Linux 3.10.0-229.el7.x86_64' --class rhel fedora \
--class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option \
'gnulinux-3.10.0-229.el7.x86_64-advanced-299bdc5b-de6d-486a-a0d2-375402aaab27' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2' 94ac5f77-cb8a-495e-a65b-...
else
search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
fi
linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro \
rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet \
LANG=zh_TW.UTF-8
initrd16 /initramfs-3.10.0-229.el7.x86_64.img
}
### END /etc/grub.d/10_linux ###
.....(中間省略).....
### BEGIN /etc/grub.d/30_os-prober ###
### END /etc/grub.d/30_os-prober ###
### BEGIN /etc/grub.d/40_custom ###
### END /etc/grub.d/40_custom ###
.....(下面省略).....
```
基本上,grub2 不希望你自己修改 grub.cfg 這個配置文件,取而代之的是修改幾個特定的配置文件之后,由 grub2-mkconfig 這個指令來產生新的 grub.cfg 文件。 不過,你還是得要了解一下 grub2.cfg 的大致內容。
在 grub.cfg 最開始的部份,其實大多是環境設置與默認值設置等,比較重要的當然是默認由哪個選項開機 (set default) 以及默認的秒數 (set timeout), 再來則是每一個菜單的設置,就是在“ menuentry ”這個設置值之后的項目啰!在鳥哥默認的配置文件當中,其實是有兩個 menuentry 的, 也就是說,鳥哥的測試機在開機的時候應該就會有兩個可以選擇的菜單的意思啰!
在 menuentry 之后會有幾個項目的規范,包括“ --class, --unrestricted --id ”等等的指定項目,之后通過“ { } ”將這個菜單會用到的數據框起來, 在選擇這個菜單之后就會進行括號內的動作的意思。如果真的點選了這個菜單,那 grub2 首先會載入模塊,例如上表中的“ load_video, insmod gzio, insmod part_gpt, insmod xfs ”等等的項目, 都是在載入要讀取核心文件所需要的磁盤、分區、文件系統、解壓縮等等的驅動程序。之后就是三個比較重要的項目:
* set root='hd0,gpt2'
這 root 是指定 grub2 配置文件所在的那個設備。以我們的測試機來說,當初安裝的時候分區出 / 與 /boot 兩個設備唷,而 grub2 是在 /boot/grub2 這個位置上, 而這個位置的磁盤文件名為 /dev/vda2 ,因此完整的 grub2 磁盤名稱就是 (hd0,2) 啰!因為我們的系統用的是 GTP 的磁盤分區格式, 因此全名就是“ hd0,gpt2 ”!這樣說,有沒有聽懂啊?
* linux16 /vmlinuz-... root=/dev/mapper/centos-root ...
這個就是 Linux 核心文件以及核心執行時所下達的參數。你應該會覺得比較怪的是,我們的核心文件不是 /boot/vmlinuz-xxx 嗎? 怎么這里的設置會是在根目錄呢?這個跟上面的 root 有關啦!大部分的系統大多有 /boot 這個分區,如果 /boot 沒有分區, 那會是怎么回事呢?我們用下面的疊代來說明一下:
* 如果沒有 /boot 分區,僅有 / 分區:所以文件名會這樣變化喔:
/boot/vmlinuz-xxx --> (/)/boot/vmlinuz-xxx --> (hd0,msdos1)/boot/vmlinuz-xxx
* 如果 /boot 是獨立分區,則文件名的變化會是這樣:
/boot/vmlinuz-xxx --> (/boot)/vmlinuz-xxx --> (hd0,msdos1)/vmlinuz-xxx因此,這個 linux16 后面接的文件名得要跟上面的 root 搭配在一起,才是完整的絕對路徑文件名喔!看懂了嗎?至于 linux16 /vmlinuz-xxx root=/file/name 那個 root 指的是“ linux 文件系統中,根目錄是在哪個設備上”的意思!從本章一開始的開機流程中,我們就知道核心會主動去掛載根目錄,并且從根目錄中讀取配置文件, 再進一步開始開機流程。所以,核心文件后面一定要接根目錄的設備啊!這樣理解吧?我們從 /etc/fstab 里面也知道根目錄的掛載可以是設備文件名、 UUID 與 LABEL 名稱,因此這個 root 后面也是可以帶入類似 root=UUID=1111.2222.33... 之類的模式喔!
* initrd16 /initramfs-3.10...
這個就是 initramfs 所在的文件名,跟 linux16 那個 vmlinuz-xxx 相同,這個文件名也是需要搭配“ set root=xxx ”那個項目的設備, 才會得到正確的位置喔!注意注意!
### 19.3.3 grub2 配置文件維護 /etc/default/grub 與 /etc/grub.d
前一個小節我們談到的是 grub2 的主配置文件 grub.cfg 約略的內容,但是因為該文件的內容太過復雜,數據量非常龐大,grub2 官方說明不建議我們手動修改! 而是應該要通過 /etc/default/grub 這個主要環境配置文件與 /etc/grub.d/ 目錄內的相關配置文件來處理比較妥當! 我們先來聊聊 /etc/default/grub 這個主要環境配置文件好了!
* /etc/default/grub 主要環境配置文件
這個主配置文件的內容大概是長這樣:
```
[root@study ~]# cat /etc/default/grub
GRUB_TIMEOUT=5 # 指定默認倒數讀秒的秒數
GRUB_DEFAULT=saved # 指定默認由哪一個菜單來開機,默認開機菜單之意
GRUB_DISABLE_SUBMENU=true # 是否要隱藏次菜單,通常是藏起來的好!
GRUB_TERMINAL_OUTPUT="console" # 指定數據輸出的終端機格式,默認是通過文字終端機
GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet"
# 就是在 menuentry 括號內的 linux16 項目后續的核心參數
GRUB_DISABLE_RECOVERY="true" # 取消救援菜單的制作
```
有興趣的伙伴請自行 info grub 并且找到 6.1 的章節閱讀一下~我們下面主要談的是幾個重要的設置項目而已。現在來說說處理的項目重點吧!
* 倒數時間參數: GRUB_TIMEOUT
這個設置值相當簡單,后面就是接你要倒數的秒數即可~例如要等待 30 秒,就在這邊改成“GRUB_TIMEOUT=30”即可!如果不想等待則輸入 0 , 如果一定要使用者選擇,則填 -1 即可!
* 是否隱藏菜單項目:GRUB_TIMEOUT_STYLE
這個項目可選擇的設置值有 menu, countdown, hidden 等等。如果沒有設置,默認是 menu 的意思。這個項目主要是在設置要不要顯示菜單! 如果你不想要讓使用者看到菜單,這里可以設置為 countdown!那 countdown 與 hidden 有啥差異呢?countdown 會在屏幕上顯示剩余的等待秒數, 而 hidden 則空空如也~除非你有特定的需求,否則這里一般鳥哥建議設置為 menu 較佳啦!
* 訊息輸出的終端機模式:GRUB_TERMINAL_OUTPUT
這個項目是指定輸出的畫面應該使用哪一個終端機來顯示的意思,主要的設置值有“ console, serial, gfxterm, vga_text ”等等。 除非有特別的需求,否則一般使用 console 即可!
* 默認開機菜單項目:GRUB_DEFAULT
這個項目在指定要用哪一個菜單 (menuentry) 來作為默認開機項目的意思。能使用的設置值包括有“ saved, 數字, title 名, ID 名”等等。 假設你有三筆 menuentry 的項目大約像這樣:
```
menuentry '1st linux system' --id 1st-linux-system { ...}
menuentry '2nd linux system' --id 2nd-linux-system { ...}
menuentry '3rd win system' --id 3rd-win-system { ...}
```
幾個常見的設置值是這樣的:
```
[root@study ~]#
GRUB_DEFAULT=1
代表使用第二個 menuentry 開機,因為數字的編號是以 0 號開始編的!
GRUB_DEFAULT=3rd-win-system
代表使用第三個 menuentry 開機,因為里頭代表的是 ID 的項目!它會找到 --id 喔!
GRUB_DEFAULT=saved
代表使用 grub2-set-default 來設置哪一個 menuentry 為默認值的意思。通常默認為 0
```
一般來說,默認就是以第一個開機菜單來作為默認項目,如果想要有不同的菜單設置,可以在這個項目填選所需要的 --id 即可。 當然啦,你的 id 就應該不要重復啰!
* 核心的外加參數功能:GRUB_CMDLINE_LINUX
如果你的核心在啟動的時候還需要加入額外的參數,就在這里加入吧!舉例來說,如果你除了默認的核心參數之外,還需要讓你的磁盤讀寫機制為 deadline 這個機制時, 可以這樣處理:
```
GRUB_CMDLINE_LINUX="..... crashkernel=auto rhgb quiet elevator=deadline"
```
在暨有的項目之后加上如同上表的設置,這樣就可以在開機時額外的加入磁盤讀寫的機制項目設置了!
這個主要環境配置文件編寫完畢之后,必須要使用 grub2-mkconfig 來重建 grub.cfg 才行喔!因為主配置文件就是 grub.cfg 而已, 我們是通過許多腳本的協力來完成 grub.cfg 的自動創建。當然啰,額外自己設置的項目,就是寫入 /etc/default/grub 文件內就是了。 我們來測試一下下面調整項目,看看你會不會修訂主要環境配置文件了呢?
問:假設你需要 (1)開機菜單等待 40 秒鐘、 (2)默認用第一個菜單開機、 (3)菜單請顯示出來不要隱藏、 (4)核心外帶“elevator=deadline”的參數值, 那應該要如何處理 grub.cfg 呢?答:直接編輯主要環境配置文件后,再以 grub2-mkconfig 來重建 grub.cfg 喔!
```
# 1\. 先編輯主要環境配置文件:
[root@study ~]# vim /etc/default/grub
GRUB_TIMEOUT=40
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=menu
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb
quiet elevator=deadline"
GRUB_DISABLE_RECOVERY="true"
# 2\. 開始重新創建 grub.cfg !
[root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-229.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-229.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-309eb890d09f440681f596543d95ec7a
Found initrd image: /boot/initramfs-0-rescue-309eb890d09f440681f596543d95ec7a.img
done
# 3\. 檢查看看 grub.cfg 的內容是否真的是改變了?
[root@study ~]# grep timeout /boot/grub2/grub.cfg
set timeout_style=menu
set timeout=40
[root@study ~]# grep default /boot/grub2/grub.cfg
set default="0"
[root@study ~]# grep linux16 /boot/grub2/grub.cfg
linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/.... elevator=deadline
linux16 /vmlinuz-0-rescue-309eb890d09f440681f5965.... elevator=deadline
```
* 菜單創建的腳本 /etc/grub.d/*
你應該會覺得很奇怪, grub2-mkconfig 執行之后,屏幕怎么會主動的去抓到 linux 的核心,還能夠找到對應核心版本的 initramfs 呢? 怎么這么厲害?其實 grub2-mkconfig 會去分析 /etc/grub.d/* 里面的文件,然后執行該文件來創建 grub.cfg 的啦! 所以啰, /etc/grub.d/* 里面的文件就顯得很重要了。一般來說,該目錄下會有這些文件存在:
* 00_header:主要在創建初始的顯示項目,包括需要載入的模塊分析、屏幕終端機的格式、倒數秒數、菜單是否需要隱藏等等,大部分在 /etc/default/grub 里面所設置的變量,大概都會在這個腳本當中被利用來重建 grub.cfg 。
* 10_linux:根據分析 /boot 下面的文件,嘗試找到正確的 linux 核心與讀取這個核心需要的文件系統模塊與參數等,都在這個腳本運行后找到并設置到 grub.cfg 當中。 因為這個腳本會將所有在 /boot 下面的每一個核心文件都對應到一個菜單,因此核心文件數量越多,你的開機菜單項目就越多了。 如果未來你不想要舊的核心出現在菜單上,那可以通過移除舊核心來處理即可。
* 30_os-prober:這個腳本默認會到系統上找其他的 partition 里面可能含有的操作系統,然后將該操作系統做成菜單來處理就是了。 如果你不想要讓其他的操作系統被偵測到并拿來開機,那可以在 /etc/default/grub 里面加上“ GRUB_DISABLE_OS_PROBER=true ”取消這個文件的運行。
* 40_custom:如果你還有其他想要自己手動加上去的菜單項目,或者是其他的需求,那么建議在這里補充即可!
所以,一般來說,我們會更動到的就是僅有 40_custom 這個文件即可。那這個文件內容也大多在放置管理員自己想要加進來的菜單項目就是了。 好了,那問題來了,我們知道 menuentry 就是一個菜單,那后續的項目有哪些東西呢?簡單的說,就是這個 menuentry 有幾種常見的設置? 亦即是 menuentry 的功能啦!常見的有這幾樣:
* 直接指定核心開機
基本上如果是 Linux 的核心要直接被用來開機,那么你應該要通過 grub2-mkconfig 去抓 10_linux 這個腳本直接制作即可,因此這個部份你不太需要記憶! 因為在 grub.cfg 當中就已經是系統能夠捉到的正確的核心開機菜單了!不過如果你有比較特別的參數需要進行呢?這時候你可以這樣作: (1)先到 grub.cfg 當中取得你要制作的那個核心的菜單項目,然后將它復制到 40_custom 當中 (2)再到 40_custom 當中依據你的需求修改即可。
這么說或許你很納悶,我們來做個實際練習好了:
問:如果你想要使用第一個原有的 menuentry 取出來后,增加一個菜單,該菜單可以強制 systemd 使用 graphical.target 來啟動 Linux 系統, 讓該菜單一定可以使用圖形界面而不用理會 default.target 的鏈接,該如何設計?答:當核心外帶參數中,有個“ systemd.unit=??? ”的外帶參數可以指定特定的 target 開機!因此我們先到 grub.cfg 當中,去復制第一個 menuentry , 然后進行如下的設置:
```
[root@study ~]# vim /etc/grub.d/40_custom
menuentry 'My graphical CentOS, with Linux 3.10.0-229.el7.x86_64' --class rhel fedora
--class gnu-linux --class gnu --class os --unrestricted --id 'mygraphical' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2' 94ac5f77-cb8a-495e-a65b-...
else
search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
fi
linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=
centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet
elevator=deadline systemd.unit=graphical.target
initrd16 /initramfs-3.10.0-229.el7.x86_64.img
}
# 請注意,上面的數據都是從 grub.cfg 里面復制過來的,增加的項目僅有特殊字體的部份而已!
# 同時考慮畫面寬度,該項目稍微被變動過,請依據您的環境來設置喔!
[root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
```
當你再次 reboot 時,系統就會多出一個菜單給你選擇了!而且選擇該菜單之后,你的系統就可以直接進入圖形界面 (如果有安裝相關的 X window 軟件時), 而不必考慮 default.target 是啥東西了!了解乎?
* 通過 chainloader 的方式移交 loader 控制權
所謂的 chain loader (開機管理程序的鏈結) 僅是在將控制權交給下一個 boot loader 而已, 所以 grub2 并不需要認識與找出 kernel 的文件名 ,“ 他只是將 boot 的控制權交給下一個 boot sector 或 MBR 內的 boot loader 而已 ” 所以通常他也不需要去查驗下一個 boot loader 的文件系統!
一般來說, chain loader 的設置只要兩個就夠了,一個是預計要前往的 boot sector 所在的分區代號, 另一個則是設置 chainloader 在那個分區的 boot sector (第一個扇區) 上!假設我的 Windows 分區在 /dev/sda1 ,且我又只有一顆硬盤,那么要 grub 將控制權交給 windows 的 loader 只要這樣就夠了:
```
menuentry "Windows" {
insmod chain # 你得要先載入 chainloader 的模塊對吧?
insmod ntfs # 建議加入 windows 所在的文件系統模塊較佳!
set root=(hd0,1) # 是在哪一個分區~最重要的項目!
chainloader +1 # 請去 boot sector 將 loader 軟件讀出來的意思!
}
```
通過這個項目我們就可以讓 grub2 交出控制權了!
問:假設你的測試系統上面使用 MBR 分區,并且出現如下的數據:
```
[root@study ~]# fdisk -l /dev/vda
Device Boot Start End Blocks Id System
/dev/vda1 2048 10487807 5242880 83 Linux
/dev/vda2 * 10487808 178259967 83886080 7 HPFS/NTFS/exFAT
/dev/vda3 178259968 241174527 31457280 83 Linux
```
其中 /dev/vda2 使用是 windows 7 的操作系統。現在我需要增加兩個開機選項,一個是取得 windows 7 的開機菜單,一個是回到 MBR 的默認環境,應該如何處理呢?答:windows 7 在 /dev/vda2 亦即是 hd0,msdos2 這個地方,而 MBR 則是 hd0 即可,不需要加上分區啊!因此整個設置會變這樣:
```
[root@study ~]# vim /etc/grub.d/40_custom
menuentry 'Go to Windows 7' --id 'win7' {
insmod chain
insmod ntfs
set root=(hd0,msdos2)
chainloader +1
}
menuentry 'Go to MBR' --id 'mbr' {
insmod chain
set root=(hd0)
chainloader +1
}
[root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
```
另外,如果每次都想要讓 windows 變成默認的開機選項,那么在 /etc/default/grub 當中設置好“ GRUB_DEFAULT=win7 ” 然后再次 grub2-mkconfig 這樣即可啦!不要去算 menuentry 的順序喔!通過 --id 內容來處理即可!
### 19.3.4 initramfs 的重要性與創建新 initramfs 文件
我們在本章稍早之前“ [boot loader 與 kernel 載入](../Text/index.html#startup_loader)”的地方已經提到過 initramfs 這玩意兒,他的目的在于提供開機過程中所需要的最重要核心模塊,以讓系統開機過程可以順利完成。 會需要 initramfs 的原因,是因為核心模塊放置于 /lib/modules/$(uname -r)/kernel/ 當中, 這些模塊必須要根目錄 (/) 被掛載時才能夠被讀取。但是如果核心本身不具備磁盤的驅動程序時, 當然無法掛載根目錄,也就沒有辦法取得驅動程序,因此造成兩難的地步。
initramfs 可以將 /lib/modules/.... 內的“開機過程當中一定需要的模塊”包成一個文件 (文件名就是 initramfs), 然后在開機時通過主機的 INT 13 硬件功能將該文件讀出來解壓縮,并且 initramfs 在內存內會仿真成為根目錄, 由于此虛擬文件系統 (Initial RAM Disk) 主要包含磁盤與文件系統的模塊,因此我們的核心最后就能夠認識實際的磁盤, 那就能夠進行實際根目錄的掛載啦!所以說:“initramfs 內所包含的模塊大多是與開機過程有關,而主要以文件系統及硬盤模塊 (如 usb, SCSI 等) 為主”的啦!
一般來說,需要 initramfs 的時刻為:
* 根目錄所在磁盤為 SATA、USB 或 SCSI 等連接接口;
* 根目錄所在文件系統為 LVM, RAID 等特殊格式;
* 根目錄所在文件系統為非傳統 Linux 認識的文件系統時;
* 其他必須要在核心載入時提供的模塊。

**Tips** 之前鳥哥忽略 initrd 這個文件的重要性,是因為鳥哥很窮... ^_^。因為鳥哥的 Linux 主機都是較早期的硬件, 使用的是 IDE 接口的硬盤,而且并沒有使用 LVM 等特殊格式的文件系統,而 Linux 核心本身就認識 IDE 接口的磁盤, 因此不需要 initramfs 也可以順利開機完成的。自從 SATA 硬盤流行起來后,沒有 initramfs 就沒辦法開機了! 因為 SATA 硬盤使用的是 SCSI 模塊來驅動的,而 Linux 默認將 SCSI 功能編譯成為模塊....
一般來說,各 distribution 提供的核心都會附上 initramfs 文件,但如果你有特殊需要所以想重制 initramfs 文件的話, 可以使用 dracut / mkinitrd 來處理的。這個文件的處理方式很簡單, man dracut 或 man mkinitrd 就知道了! ^_^。 CentOS 7 應該要使用 dracut 才對,不過 mkinitrd 還是有保留下來,兩者隨便你玩!鳥哥這里主要是介紹 dracut 就是了!
```
[root@study ~]# dracut [-fv] [--add-drivers 列表] initramfs文件名 核心版本
選項與參數:
-f :強迫編譯出 initramfs ,如果 initramfs 文件已經存在,則覆蓋掉舊文件
-f :顯示 dracut 的運行過程
--add-drivers 列表:在原本的默認核心模塊中,增加某些你想要的模塊!模塊位于核心所在目錄
/lib/modules/$(uname -r)/kernel/*
initramfs文件名 :就是你需要的文件名!開頭最好就是 initramfs,后面接版本與功能
核心版本 :默認當然是目前運行中的核心版本,不過你也可以手動輸入其他不同版本!
其實 dracut 還有很多功能,例如下面的幾個參數也可以參考看看:
--modules :將 dracut 所提供的開機所需模塊 (核心核模塊) 載入,可用模塊在下面的目錄內
/usr/lib/dracut/modules.d/
--gzip|--bzip2|--xz:嘗試使用哪一種壓縮方式來進行 initramfs 壓縮。默認使用 gzip 喔!
--filesystems :加入某些額外的文件系統支持!
范例一:以 dracut 的默認功能創建一個 initramfs 虛擬磁盤文件
[root@study ~]# dracut -v initramfs-test.img $(uname -r)
Executing: /sbin/dracut -v initramfs-test.img 3.10.0-229.el7.x86_64
*** Including module: bash *** # 先載入 dracut 本身的模塊支持
*** Including module: nss-softokn ***
*** Including modules done ***
.....(中間省略)..... # 下面兩行在處理核心模塊
*** Installing kernel module dependencies and firmware ***
*** Installing kernel module dependencies and firmware done ***
.....(中間省略).....
*** Generating early-microcode cpio image *** # 創建微指令集
*** Constructing GenuineIntel.bin ****
*** Store current command line parameters ***
*** Creating image file *** # 開始創建 initramfs 啰!
*** Creating image file done ***
范例二:額外加入 e1000e 網卡驅動與 ext4/nfs 文件系統在新的 initramfs 內
[root@study ~]# dracut -v --add-drivers "e1000e" --filesystems "ext4 nfs" \
> initramfs-new.img $(uname -r)
[root@study ~]# lsinitrd initramfs-new.img | grep -E '(e1000|ext4|nfs)'
usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e
usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4
usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4/ext4.ko
usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs
usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs/nfs.ko
# 你可以看得到,新增的模塊現在正在新的 initramfs 當中了呢!很愉快喔!
```
initramfs 創建完成之后,同時核心也處理完畢后,我們就可以使用 grub2 來創建菜單了!下面繼續瞧一瞧吧!
### 19.3.5 測試與安裝 grub2
如果你的 Linux 主機本來就是使用 grub2 作為 loader 的話,那么你就不需要重新安裝 grub2 了, 因為 grub2 本來就會主動去讀取配置文件啊!您說是吧!但如果你的 Linux 原來使用的并非 grub2 , 那么就需要來安裝啦!如何安裝呢?首先,你必須要使用 grub-install 將一些必要的文件復制到 /boot/grub2 里面去,你應該這樣做的:
```
[root@study ~]# grub2-install [--boot-directory=DIR] INSTALL_DEVICE
選項與參數:
--boot-directory=DIR 那個 DIR 為實際的目錄,使用 grub2-install 默認會將
grub2 所有的文件都復制到 /boot/grub2/* ,如果想要復制到其他目錄與設備去,
就得要用這個參數。
INSTALL_DEVICE 安裝的設備代號啦!
范例一:將 grub2 安裝在目前系統的 MBR 下面,我的系統為 /dev/vda:
[root@study ~]# grub2-install /dev/vda
# 因為原本 /dev/vda 就是使用 grub2 ,所以似乎不會出現什么特別的訊息。
# 如果去查閱一下 /boot/grub2 的內容,會發現所有的文件都更新了,因為我們重裝了!
# 但是注意到,我們并沒有配置文件喔!那要自己創建!
```
基本上,grub2-install 大概僅能安裝 grub2 主程序與相關軟件到 /boot/grub2/ 那個目錄去,如果后面的設備填的是整個系統 (/dev/vda, /dev/sda...), 那 loader 的程序才會寫入到 MBR 里面去。如果是 XFS 文件系統的 /dev/vda2 設備的話 (個別 partition),那 grub2-install 就會告訴你, 該文件系統并不支持 grub2 的安裝喔!也就是你不能用 grub2-install 將你的主程序寫入到 boot sector 里頭去的意思啦! 那怎辦?沒關系,來強迫寫入一下看看!
```
# 嘗試看一下你的系統中有沒有其他的 xfs 文件系統,且為傳統的 partition 類型?
[root@study ~]# df -T |grep -i xfs
/dev/mapper/centos-root xfs 10475520 4128728 6346792 40% /
/dev/mapper/centos-home xfs 5232640 665544 4567096 13% /home
/dev/mapper/raidvg-raidlv xfs 1558528 33056 1525472 3% /srv/raidlvm
/dev/vda2 xfs 1038336 144152 894184 14% /boot
/dev/vda4 xfs 1038336 63088 975248 7% /srv/myproject
# 看起來僅有 /dev/vda4 比較適合做個練習的模樣了!來瞧瞧先!
# 將 grub2 的主程序安裝到 /dev/vda4 去看看!
[root@study ~]# grub2-install /dev/vda4
Installing for i386-pc platform.
grub2-install: error: hostdisk//dev/vda appears to contain a xfs filesystem which isn't
known to reserve space for DOS-style boot. Installing GRUB there could result in
FILESYSTEM DESTRUCTION if valuable data is overwritten by grub-setup (--skip-fs-probe
disables this check, use at your own risk).
# 說是 xfs 恐怕不能支持你的 boot sector 概念!這個應該是誤判!所以我們還是給它強制裝一下!
[root@study ~]# grub2-install --skip-fs-probe /dev/vda4
Installing for i386-pc platform.
grub2-install: warning: File system ‘xfs’ doesn't support embedding.
grub2-install: warning: Embedding is not possible. GRUB can only be installed in this
setup by using blocklists. However, blocklists are UNRELIABLE and their use is
discouraged..
grub2-install: error: will not proceed with blocklists.
# 還是失敗!因為還是擔心 xfs 被搞死~好!沒問題!加個 --force 與 --recheck 重新處理一遍!
[root@study ~]# grub2-install --force --recheck --skip-fs-probe /dev/vda4
Installing for i386-pc platform.
grub2-install: warning: File system ‘xfs’ doesn't support embedding.
grub2-install: warning: Embedding is not possible. GRUB can only be installed in this
setup by using blocklists. However, blocklists are UNRELIABLE and their use is
discouraged..
Installation finished. No error reported.
# 注意看!原本是無法安裝的錯誤,現在僅有 warning 警告訊息,所以這樣就安裝到 partition 上了!
```
上面這樣就將 grub2 的主程序安裝到 /dev/vda4 以及重新安裝到 MBR 里面去了。現在來思考一下,我們知道 grub2 主程序會去找 grub.cfg 這個文件,大多是在 /boot/grub2/grub.cfg 里面,那有趣了,我們的 MBR 與 /dev/vda4 都是到 /boot/grub2/grub.cfg 去抓設置嗎? 如果是多重操作系統那怎辦?呵呵!這就需要重新進入新系統才能夠安裝啦!舉個例子來說啰:
問:假設你的測試系統上面使用 MBR 分區,并且出現如下的數據:
```
[root@study ~]# fdisk -l /dev/vda
Device Boot Start End Blocks Id System
/dev/vda1 2048 10487807 5242880 83 Linux
/dev/vda2 * 10487808 178259967 83886080 7 HPFS/NTFS/exFAT
/dev/vda3 178259968 241174527 31457280 83 Linux
```
其中 /dev/vda1, /dev/vda3 是兩個 CentOS 7 系統,而 /dev/vda2 則是 windows 7 系統。安裝的流程是依序 /dev/vda1 --> /dev/vda2 --> /dev/vda3。因此,安裝好而且重新開機后,系統其實是默認進入 /dev/vda3 這個 CentOS 7 的系統的。 此時 MBR 會去讀取的配置文件在 (/dev/vda3)/boot/grub2/grub.cfg 才對。
因為 /dev/vda1 應該是用來管理開機菜單的,而 /dev/vda2 及 /dev/vda3 在規劃中就是用來讓學生操作的,因此默認情況下, /dev/vda1 內的 CentOS 系統應該只會在開機的時候用到而已,或者是出問題時會找他來使用。至于 /dev/vda3 及 /dev/vda2 則可能因為學生的誤用, 因此未來可能會升級或刪除或重灌等。那你如何讓系統永遠都是使用 /dev/vda1 開機呢?答:因為 MBR 的 boot loader 應該要去 (/dev/vda1)/boot/grub2/grub.cfg 讀取相關設置才是正常的!所以,你可以使用幾種基本的方式來處理:
* 因為 CentOS 7 會主動找到其他操作系統,因此你可以在 /dev/vda3 的開機菜單中找到 /dev/vda1 的開機選項,請用該選項進入系統, 你就能夠進入 /dev/vda1 了!
* 假設沒能抓到 /dev/vda1 ,那你可以在 /dev/vda3 下面使用 chroot 來進入 /dev/vda1 喔!
* 使用救援光盤去抓到正確的 /dev/vda1,然后取得 /dev/vda1 的系統喔!
等到進入系統后,修改 /etc/default/grub 及 /etc/grub.d/40_custom 之后,使用 grub2-mkconfig -o /boot/grub2/grub.cfg , 然后重新 grub2-install /dev/vda 就能夠讓你的 MBR 去取得 /dev/vda1 內的配置文件啰!
問:依據 19.3.3 小節的第一個練習,我們的測試機目前為 40 秒倒數,且有一個強制進入圖形界面的“ My graphical CentOS7 ”菜單! 現在我們想要多加兩個菜單,一個是回到 MBR 的 chainloader,一個是使用 /dev/vda4 的 chainloader,該如何處理?答:因為沒有必要重新安裝 grub2 ,直接修改即可。修改 40_custom 成為這樣:
```
[root@study ~]# vim /etc/grub.d/40_custom
# 最下面加入這兩個項目即可!
menuentry 'Goto MBR' {
insmod chain
insmod part_gpt
set root=(hd0)
chainloader +1
}
menuentry 'Goto /dev/vda4' {
insmod chain
insmod part_gpt
set root=(hd0.gpt4)
chainloader +1
}
[root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
```
最后總結一下:
1. 如果是從其他 boot loader 轉成 grub2 時,得先使用 grub2-install 安裝 grub2 配置文件;
2. 承上,如果安裝到 partition 時,可能需要加上額外的許多參數才能夠順利安裝上去!
3. 開始編輯 /etc/default/grub 及 /etc/grub.d/* 這幾個重要的配置文件;
4. 使用 grub2-mkconfig -o /boot/grub2/grub.cfg 來創建開機的配置文件!
### 19.3.6 開機前的額外功能修改
事實上,前幾個小節設置好之后,你的 grub2 就已經在你的 Linux 系統上面了,而且同時存在于 MBR 與 boot sector 當中呢!所以,我們已經可以重新開機來查閱看看啦! 另外,如果你正在進行開機,那么請注意,我們可以在默認菜單 (鳥哥的范例當中是 40 秒) 按下任意鍵, 還可以進行 grub2 的“線上編修”功能喔!真是棒啊!先來看看開機畫面吧!
圖19.3.1、grub2 開機畫面示意圖
由于默認菜單就沒有隱藏,因此你會直接看到這 5 個菜單而已,同時會有讀秒的咚咚在倒數。 菜單部分的畫面其實就是 menuentry 后面的文字啦!你現在知道如何修改 menuentry 后面的文字了吧! ^_^。 然后如果你點選了“Goto MBR”與“Goto /dev/vda4”時,怪了!怎么發現到菜單又重新回來了呢? 這是因為這兩個 Goto 的菜單都是重新讀取主配置文件,而 MBR 與 /dev/vda4 配置文件的讀取都是來自 (/dev/vda2)/boot/grub2/grub.cfg 的緣故! 因此這個畫面就會重復出現了!這樣了解乎?
另外,如果你再仔細看的話,會發現到上圖中底部還有一些細部的選項,似乎有個 'e' edit 的樣子! 沒錯~ grub2 支持線上編修指令喔!這是個很有用的功能!假如剛剛你將 grub.cfg 的內容寫錯了,導致出現無法開機的問題時, 我們可以查閱該 menuentry 菜單的內容并加以修改喔!舉例來說,我想要知道第一個菜單的實際內容時,將反白光棒移動到第一個菜單, 再按下 'e' 會進入如下畫面:
圖19.3.2、grub2 額外的指令編輯模式
因為 CentOS 7 默認沒有提供美美的底圖給我們使用,因此這里會看到無法分辨的兩個區塊!事實上它真的是兩個區塊, 上方是實際你可以編輯的內容區段,仔細看,這不就是我們在 grub.cfg 里面設置的東西嗎?沒錯!此時你還可以繼續進一步修改喔! 用上/下/左/右按鍵到你想要編輯的地方,直接刪除、新增即可!
至于下方畫面則僅是一些編輯說明,重點在告訴你,編輯完畢之后,若想要取消而回到前一個畫面,請使用 [crtl]+c 或者是 [esc] 回去, 若是修改完畢,想要直接開機時,請使用 [crtl]+x 來開機啰!
問:現在我想要讓系統開機的過程中,讓這個系統進入救援模式 (rescue) ,而不想要進入系統后使用 systemctl rescue 時,該如何處理?答:仔細看到圖 19.3.2 的畫面,按下“向下”的方向鍵,直到出現 linux16 那一行,然后在那一行的最后面加上 systemd.unit=rescue.target , 畫面有點像這樣:
然后再按下 [crtl]+x 來進入系統,就能夠取得 rescue 的環境了!登陸后有點像這樣:
接著下來你就可以開始救援系統啰!
你可能會覺得很訝異!早期 SystemV 的系統中,進入 runlevel 1 的狀態是不需要輸入 root 密碼的,在 systemd 的年代,哇!! 竟然需要密碼才能夠進入救援模式耶!而且是強制要有 root 密碼耶!如果你是 root 密碼忘記要救援,救個鬼啊~還是需要 root 密碼啊! 那怎辦?沒關系~本章稍后會告訴你應該要如何處理的啦!
### 19.3.7 關于開機畫面與終端機畫面的圖形顯示方式
如果你想要讓你的開機畫面使用圖形顯示方式,例如使用中文來顯示你的畫面啊!因為我們默認的 locale 語系就是 zh_TW.utf8 嘛! 所以理論上 grub2 會顯是中文出來才對啊!有沒有辦法達成呢?是有的~通過圖形顯是的方法即可!不過, 我們得要重新修改 grub.cfg 才行喔!依據下面的方式來處理:
```
# 先改重要的配置文件
[root@study ~]# vim /etc/default/grub
.....(前面省略).....
GRUB_TERMINAL=gfxterm # 設置主要的終端機顯示為圖形界面!
GRUB_GFXMODE=1024x768x24 # 圖形界面的 X, Y, 彩度數據
GRUB_GFXPAYLOAD_LINUX=keep # 保留圖形界面,不要使用 text 喔!
# 重新創建配置文件
[root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
```
再次的重新開機,這時你會看到有點像下面的模樣的畫面喔!
圖19.3.3、使用圖形顯示模式的開機畫面
看到沒有?上圖中有繁體中文喔!中文喔喔喔喔喔喔~真是開心啊! 未來如果你有需要在你的開機菜單當中加入許多屬于你自己的公司/企業的畫面,那就太容易啰! ^_^
### 19.3.8 為個別菜單加上密碼
想像一個環境,如果你管理的是一間計算機教室,這間計算機教室因為可對外開放,但是你又擔心某些 partition 被學生不小心的弄亂,因此你可能會想要將某些開機菜單作個保護。這個時候,為每個菜單作個加密的密碼就是個可行的方案啦!
另外,從本章前面的 19.3.6 小節介紹的開機過程中,你會知道使用者可以在開機的過程中于 grub2 內選擇進入某個菜單,以及進入 grub2 指令模式去修改菜單的參數數據等。 也就是說,主要的 grub2 控制有: (1)grub2 的菜單命令行修改與 (2)進入選擇的菜單開機流程。好了,如剛剛談到的計算機教室案例, 你要怎么讓某些密碼可以完整的掌控 grub2 的所有功能,某些密碼則只能進入個別的菜單開機呢?這就得要牽涉到 grub2 的帳號機制了!
* grub2 的帳號、密碼與菜單設置
grub2 有點在仿真 Linux 的帳號管理方案喔!因為在 grub2 的菜單管理中,有針對兩種身份進行密碼設置:
* superusers: 設置系統管理員與相關參數還有密碼等,使用這個密碼的用戶,將可在 grub2 內具有所有修改的權限。 但一旦設置了這個 superusers 的參數,則所有的指令修改將會被變成受限制的!
* users: 設置一般帳號的相關參數與密碼,可以設置多個用戶喔!使用這個密碼的用戶可以選擇要進入某些菜單項目。 不過,菜單項目也得要搭配相對的帳號才行喔!(一般來說,使用這種密碼的帳號并不能修改菜單的內容,僅能選擇進入菜單去開機而已)
這樣說可能你不是很容易看得懂,我們使用下面的一個范例來說明你就知道怎么處理了。另外,下面的范例是單純給讀者們看看而已的~ 不能夠直接用在我們的測試機器里面喔!
問:假設你的系統有三個各別的操作系統,分別安裝在 (hd0,1), (hd0,2), (hd0,3) 當中。假設 (hd0,1) 是所有人都可以選擇進入的系統, (hd0,2) 是只有系統管理員可以進入的系統,(hd0,3)則是另一個一般用戶與系統管理員可以進入的系統。另外,假設系統管理員的帳號/密碼設置為 vbird/abcd1234, 而一般帳號為 dmtsai/dcba4321 ,那該如何設置?答:如果依據上述的說明,其實沒有用到 Linux 的 linux16 與 initrd16 的項目,只需要 chainloader 的項目而已! 因此,整個 grub.cfg 會有點像下面這樣喔:
```
# 第一個部份是先設置好管理員與一般帳號的帳號名稱與密碼項目!
set superusers="vbird" # 這里是設置系統管理員的帳號名稱為啥的意思!
password vbird abcd1234 # 當然要給予這個帳號密碼啊!
password dmtsai dcba4321 # 沒有輸入 superuses 的其他帳號,當然就是判定為一般帳號
menuentry "大家都可以選擇我來開機喔!" --unrestricted {
set root=(hd0,1)
chainloader +1
}
menuentry "只有管理員的密碼才有辦法使用" --users "" {
set root=(hd0,2)
chainloader +1
}
menuentry "只有管理員與 dmtsai 才有辦法使用喔!" --users dmtsai {
set root=(hd0,3)
chainloader +1
}
```
如上表所示,你得要使用 superuses 來指定哪個帳號是管理員!另外,這個帳號與 Linux 的實體帳號無關,這僅是用來判斷密碼所代表的意義而已。 而密碼的給予有兩種語法:
* password_pbkdf2 帳號 “使用grub2-mkpasswd-pbkdf2所產生的密碼”
* password 帳號 “沒加密的明碼”
有了帳號與密碼之后,在來就是在個別的菜單上面加上是否要取消限制 (--unrestricted) 或者是給予哪個用戶 (--users) 的設置項目。 同時請注意喔,所有的系統管理員所屬的密碼應該是能夠修改所有的菜單,因此你無須在第三個菜單上面加入 vbird 這個管理員帳號! 這樣說你就可以了解了吧?
你很可能會這樣說:“了解個頭啦!怎么可能會了解!前面不是才說過:「不要手動去修改 grub.cfg 」嗎?這里怎么直接列出 grub.cfg 的內容? 上面這些項目我是要在哪些環境配置文件里面修改啦?”呵呵~您真內行,沒有被騙耶~好厲害~好厲害!
* grub2 密碼設置的文件位置與加密的密碼
還記得我們在前幾小節談到主要的環境設置是在 /etc/grub.d/* 里面吧?里面的文件文件名有用數字開頭,那些數字照順序,就是 grub.cfg 的來源順序了。 因此最早被讀的應該是 00_header,但是那個文件的內容挺重要的,所以 CentOS 7 不建議你改它~那要改誰?就自己創建一個名為 01_users 的文件即可! 要注意是兩個數字開頭接著底線的文件名才行喔!然后將帳號與密碼參數給它補進去!
現在讓我們將 vbird 與 dmtsai 的密碼加密,實際在我們的測試機器上面創建起來吧!
```
# 1\. 先取得 vbird 與 dmtsai 的密碼。下面我僅以 vbird 來說明而已!
[root@study ~]# grub2-mkpasswd-pbkdf2
Enter password: # 這里輸入你的密碼
Reenter password: # 再一次輸入密碼
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.9A2EBF7A1F484...
# 上面特殊字體從 grub.pbkdf2.... 的那一行,全部的數據就是你的密碼喔!復制下來!
# 2\. 將密碼與帳號寫入到 01_users 文件內
[root@study ~]# vim /etc/grub.d/01_users
cat << eof
set superusers="vbird"
password_pbkdf2 vbird grub.pbkdf2.sha512.10000.9A2EBF7A1F484904FF3681F97AE22D58DFBFE65A...
password_pbkdf2 dmtsai grub.pbkdf2.sha512.10000.B59584C33BC12F3C9DB8B18BE9F557631473AED...
eof
# 請特別注意,在 /etc/grub.d/* 下面的文件是“執行腳本”檔,是要被執行的!
# 因此不能直接寫帳密,而是通過 cat 或 echo 等指令方式來將帳密數據顯示出來才行喔!
# 3\. 因為 /etc/grub.d/ 下面應該是可執行文件,所以剛剛創建的 01_users 當然要給予執行權限
[root@study ~]# chmod a+x /etc/grub.d/01_users
[root@study ~]# ll /etc/grub.d/01_users
-rwxr-xr-x. 1 root root 649 Aug 31 19:42 /etc/grub.d/01_users
```
很快的,你就已經將密碼創建妥當了!接下來就來聊一聊,那么每個 menuentry 要如何修改呢?
* 為個別的菜單設置帳號密碼的使用模式
回想一下我們之前的設置,目前測試機器的 Linux 系統菜單應該有五個:
* 來自 /etc/grub.d/10_linux 這個文件主動偵測的兩個 menuentry;
* 來自 /etc/grub.d/40_custom 這個我們自己設置的三個 menuentry
在 40_custom 內的設置,我們可以針對每個 menuentry 去調整,而且該調整是固定的,不會隨便被更改。至于 10_linux 文件中, 則每個 menuentry 的設置都會依據 10_linux 的數據去變更,也就是由 10_linux 偵測到的核心開機菜單都會是相同的意思。
因為我們已經在 01_users 文件內設置了 set superusers="vbird" 這個設置值,因此每個菜單內的參數除了知道 vbird 密碼的人之外, 已經不能隨便修改了喔!所以,選擇 10_linux 制作出來的菜單開機,應該就算正常開機,所以,我們默認不要使用密碼好了! 剛剛好 10_linux 的 menuentry 設置值就是這樣:
```
[root@study ~]# vim /etc/grub.d/10_linux
.....(前面省略).....
CLASS="--class gnu-linux --class gnu --class os --unrestricted"
# 這一行大約在 29 行左右,你可以利用 unrestricted 去搜尋即可!
# 默認已經不受限制 (--unrestricted) 了!如果想要受限制,在這里將 --unrestricted
# 改成你要使用的 --users "帳號名稱" 即可!不過,還是不建議修改啦!
```
現在我們假設在 40_custom 里面要增加一個可以進入救援模式 (rescue) 的環境,并且放置到最后一個菜單中,同時僅有知道 dmtsai 的密碼者才能夠使用, 那你應該這樣作:
```
[root@study ~]# vim /etc/grub.d/40_custom
.....(前面省略).....
menuentry 'Rescue CentOS7, with Linux 3.10.0-229.el7.x86_64' --users dmtsai {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod xfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2' 94ac5f77-cb8a-...
else
search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
fi
linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv
=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet
systemd.unit=rescue.target
initrd16 /initramfs-3.10.0-229.el7.x86_64.img
}
[root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
```
最后一步當然不要忘記重建你的 grub.cfg 啰!然后重新開機測試一下,如果一切順利,你會發現如下的畫面:
圖19.3.4、默認的菜單環境
你直接在 1, 2, 3 菜單上面按下 enter 就可以順利的繼續開機,而不用輸入任何的密碼,這是因為有 --unrestricted 參數的關系。 第 4, 5 菜單中,如果你按下 enter 的話,就會出現如下畫面:
圖19.3.5、需要輸入帳號密碼的環境
你可能會懷疑,怪了!為啥 4, 5 需要輸入密碼才行?而且一定要 vbird 這個系統管理員的密碼才可接受?使用 dmstai 就不可以! 這是因為我們在 4, 5 忘記加上 --users 也忘記加上 --restricted 了!因此這兩個項目“一定要系統管理員”才能夠進入與修改。
最后,你在第 6 個菜單上面輸入 e 來想要修改參數時,輸入的帳密確實是 dmtsai 的帳密,但是,就是無法修改參數耶!怎么回事啊? 我們前面講過了, grub2 兩個基本的功能 (1)修改參數與 (2)進入菜單開機模式,只有系統管理員能夠修改參數,一般用戶只能選擇可用的開機菜單啦! 這樣說,終于理解了吧?哈哈!
問:我的默認菜單里面沒有加上 --unrestricted 項目,同時已經設置了 set superusers="vbird" 了, 那請教一下,開機的時候能不能順利開機 (沒有輸入帳密的情況下?)答:因為沒有寫上 --unrestricted 的項目,同時又加上了 superusers="vbird" 的設置項目,這表示“ grub.cfg 內的所有參數都已經受到限制”了, 所以,當倒數讀秒結束后,系統會叫出帳號密碼輸入的窗口給你填寫,如果沒有填寫就會一直卡住了!因此無法順利開機喔!
- 鳥哥的Linux私房菜:基礎學習篇 第四版
- 目錄及概述
- 第零章、計算機概論
- 0.1 電腦:輔助人腦的好工具
- 0.2 個人電腦架構與相關設備元件
- 0.3 數據表示方式
- 0.4 軟件程序運行
- 0.5 重點回顧
- 0.6 本章習題
- 0.7 參考資料與延伸閱讀
- 第一章、Linux是什么與如何學習
- 1.1 Linux是什么
- 1.2 Torvalds的Linux發展
- 1.3 Linux當前應用的角色
- 1.4 Linux 該如何學習
- 1.5 重點回顧
- 1.6 本章習題
- 1.7 參考資料與延伸閱讀
- 第二章、主機規劃與磁盤分區
- 2.1 Linux與硬件的搭配
- 2.2 磁盤分區
- 2.3 安裝Linux前的規劃
- 2.4 重點回顧
- 2.5 本章習題
- 2.6 參考資料與延伸閱讀
- 第三章、安裝 CentOS7.x
- 3.1 本練習機的規劃--尤其是分區參數
- 3.2 開始安裝CentOS 7
- 3.3 多重開機安裝流程與管理(Option)
- 3.4 重點回顧
- 3.5 本章習題
- 3.6 參考資料與延伸閱讀
- 第四章、首次登陸與線上求助
- 4.1 首次登陸系統
- 4.2 文字模式下指令的下達
- 4.3 Linux系統的線上求助man page與info page
- 4.4 超簡單文書編輯器: nano
- 4.5 正確的關機方法
- 4.6 重點回顧
- 4.7 本章習題
- 4.8 參考資料與延伸閱讀
- 第五章、Linux 的文件權限與目錄配置
- 5.1 使用者與群組
- 5.2 Linux 文件權限概念
- 5.3 Linux目錄配置
- 5.4 重點回顧
- 5.5 本章練習
- 5.6 參考資料與延伸閱讀
- 第六章、Linux 文件與目錄管理
- 6.1 目錄與路徑
- 6.2 文件與目錄管理
- 6.3 文件內容查閱
- 6.4 文件與目錄的默認權限與隱藏權限
- 6.5 指令與文件的搜尋
- 6.6 極重要的復習!權限與指令間的關系
- 6.7 重點回顧
- 6.8 本章習題:
- 6.9 參考資料與延伸閱讀
- 第七章、Linux 磁盤與文件系統管理
- 7.1 認識 Linux 文件系統
- 7.2 文件系統的簡單操作
- 7.3 磁盤的分區、格式化、檢驗與掛載
- 7.4 設置開機掛載
- 7.5 內存交換空間(swap)之創建
- 7.6 文件系統的特殊觀察與操作
- 7.7 重點回顧
- 7.8 本章習題 - 第一題一定要做
- 7.9 參考資料與延伸閱讀
- 第八章、文件與文件系統的壓縮,打包與備份
- 8.1 壓縮文件的用途與技術
- 8.2 Linux 系統常見的壓縮指令
- 8.3 打包指令: tar
- 8.4 XFS 文件系統的備份與還原
- 8.5 光盤寫入工具
- 8.6 其他常見的壓縮與備份工具
- 8.7 重點回顧
- 8.8 本章習題
- 8.9 參考資料與延伸閱讀
- 第九章、vim 程序編輯器
- 9.1 vi 與 vim
- 9.2 vi 的使用
- 9.3 vim 的額外功能
- 9.4 其他 vim 使用注意事項
- 9.5 重點回顧
- 9.6 本章練習
- 9.7 參考資料與延伸閱讀
- 第十章、認識與學習BASH
- 10.1 認識 BASH 這個 Shell
- 10.2 Shell 的變量功能
- 10.3 命令別名與歷史命令
- 10.4 Bash Shell 的操作環境:
- 10.5 數據流重導向
- 10.6 管線命令 (pipe)
- 10.7 重點回顧
- 10.8 本章習題
- 10.9 參考資料與延伸閱讀
- 第十一章、正則表達式與文件格式化處理
- 11.1 開始之前:什么是正則表達式
- 11.2 基礎正則表達式
- 11.3 延伸正則表達式
- 11.4 文件的格式化與相關處理
- 11.5 重點回顧
- 11.6 本章習題
- 11.7 參考資料與延伸閱讀
- 第十二章、學習 Shell Scripts
- 12.1 什么是 Shell scripts
- 12.2 簡單的 shell script 練習
- 12.3 善用判斷式
- 12.4 條件判斷式
- 12.5 循環 (loop)
- 12.6 shell script 的追蹤與 debug
- 12.7 重點回顧
- 12.8 本章習題
- 第十三章、Linux 帳號管理與 ACL 權限設置
- 13.1 Linux 的帳號與群組
- 13.2 帳號管理
- 13.3 主機的細部權限規劃:ACL 的使用
- 13.4 使用者身份切換
- 13.5 使用者的特殊 shell 與 PAM 模塊
- 13.6 Linux 主機上的使用者訊息傳遞
- 13.7 CentOS 7 環境下大量創建帳號的方法
- 13.8 重點回顧
- 13.9 本章習題
- 13.10 參考資料與延伸閱讀
- 第十四章、磁盤配額(Quota)與進階文件系統管理
- 14.1 磁盤配額 (Quota) 的應用與實作
- 14.2 軟件磁盤陣列 (Software RAID)
- 14.3 邏輯卷軸管理員 (Logical Volume Manager)
- 14.4 重點回顧
- 14.5 本章習題
- 14.6 參考資料與延伸閱讀
- 第十五章、例行性工作調度(crontab)
- 15.1 什么是例行性工作調度
- 15.2 僅執行一次的工作調度
- 15.3 循環執行的例行性工作調度
- 15.4 可喚醒停機期間的工作任務
- 15.5 重點回顧
- 15.6 本章習題
- 第十六章、程序管理與 SELinux 初探
- 16.1 什么是程序 (process)
- 16.2 工作管理 (job control)
- 16.3 程序管理
- 16.4 特殊文件與程序
- 16.5 SELinux 初探
- 16.6 重點回顧
- 16.7 本章習題
- 16.8 參考資料與延伸閱讀
- 第十七章、認識系統服務 (daemons)
- 17.1 什么是 daemon 與服務 (service)
- 17.2 通過 systemctl 管理服務
- 17.3 systemctl 針對 service 類型的配置文件
- 17.4 systemctl 針對 timer 的配置文件
- 17.5 CentOS 7.x 默認啟動的服務簡易說明
- 17.6 重點回顧
- 17.7 本章習題
- 17.8 參考資料與延伸閱讀
- 第十八章、認識與分析登錄文件
- 18.1 什么是登錄文件
- 18.2 rsyslog.service :記錄登錄文件的服務
- 18.3 登錄文件的輪替(logrotate)
- 18.4 systemd-journald.service 簡介
- 18.5 分析登錄文件
- 18.6 重點回顧
- 18.7 本章習題
- 18.8 參考資料與延伸閱讀
- 第十九章、開機流程、模塊管理與 Loader
- 19.1 Linux 的開機流程分析
- 19.2 核心與核心模塊
- 19.3 Boot Loader: Grub2
- 19.4 開機過程的問題解決
- 19.5 重點回顧
- 19.6 本章習題
- 19.7 參考資料與延伸閱讀
- 第二十章、基礎系統設置與備份策略
- 20.1 系統基本設置
- 20.2 服務器硬件數據的收集
- 20.3 備份要點
- 20.4 備份的種類、頻率與工具的選擇
- 20.5 鳥哥的備份策略
- 20.6 災難復原的考慮
- 20.7 重點回顧
- 20.8 本章習題
- 20.9 參考資料與延伸閱讀
- 第二十一章、軟件安裝:源代碼與 Tarball
- 20.1 開放源碼的軟件安裝與升級簡介
- 21.2 使用傳統程序語言進行編譯的簡單范例
- 21.3 用 make 進行宏編譯
- 21.4 Tarball 的管理與建議
- 21.5 函數庫管理
- 21.6 檢驗軟件正確性
- 21.7 重點回顧
- 21.8 本章習題
- 21.9 參考資料與延伸閱讀
- 第二十二章、軟件安裝 RPM, SRPM 與 YUM
- 22.1 軟件管理員簡介
- 22.2 RPM 軟件管理程序: rpm
- 22.3 YUM 線上升級機制
- 22.4 SRPM 的使用 : rpmbuild (Optional)
- 22.5 重點回顧
- 22.6 本章習題
- 22.7 參考資料與延伸閱讀
- 第二十三章、X Window 設置介紹
- 23.1 什么是 X Window System
- 23.2 X Server 配置文件解析與設置
- 23.3 顯卡驅動程序安裝范例
- 23.4 重點回顧
- 23.5 本章習題
- 23.6 參考資料與延伸閱讀
- 第二十四章、Linux 核心編譯與管理
- 24.1 編譯前的任務:認識核心與取得核心源代碼
- 24.2 核心編譯的前處理與核心功能選擇
- 24.3 核心的編譯與安裝
- 24.4 額外(單一)核心模塊編譯
- 24.5 以最新核心版本編譯 CentOS 7.x 的核心
- 24.6 重點回顧
- 24.7 本章習題
- 24.8 參考資料與延伸閱讀