GRUB
GRUB 來自 GRand Unified Bootloader 的縮寫。它的功能是在啟動時從 BIOS 接管掌控、載入自身、載入 Linux 核心到記憶體,然後再把執行權交給核心。一旦核心開始掌控,GRUB 就完成了它的任務,也就不再需要了。
GRUB 支援多種 Linux 核心,並允許使用者在啟動時透過選單在其中選擇。我發現這是一種非常有用的工具,因為我有很多次遇到一個應用程式或者系統服務在特定核心版本下失敗的問題。有好幾次,引導到一個較舊的核心時就可以避免類似的問題。預設情況下,使用 yum 或 dnf 進行更新時會儲存三個核心 – 最新的以及兩個比較舊的。在被包管理器刪除之前所保留的核心數目可以在 /etc/dnf/dnf.conf 或 /etc/yum.conf 檔案中配置。我通常把 installonly_limit 的值修改為 9 以便保留 9 個核心。當我不得不恢復到低幾個版本的核心時這非常有用。
GRUB 選單
GRUB 選單的功能是當預設的核心不是想要的時,允許使用者從已經安裝的核心中選擇一個進行引導。透過上下箭頭鍵允許你選中想要的核心,敲擊回車鍵會使用選中的核心繼續載入程式。
GRUB 選單也提供了超時機制,因此如果使用者沒有做任何選擇,GRUB 就會在沒有使用者干預的情況下使用預設核心繼續引導。敲擊鍵盤上除了回車鍵之外的任何鍵會停止終端上顯示的倒數計時器。立即敲擊回車鍵會使用預設核心或者選中的核心繼續載入程式。
GRUB 選單提供了一個 “救援 rescue” 核心,用於故障排除或者由於某些原因導致的常規核心不能完成啟動過程。不幸的是,這個救援核心不會引導到救援模式。文章後面會更詳細介紹這方面的東西。
grub.cfg 檔案
grub.cfg 檔案是 GRUB 配置檔案。它由 grub2-mkconfig 程式根據使用者的配置使用一組主配置檔案以及 grub 預設檔案而生成。/boot/grub2/grub.cfg 檔案在 Linux 安裝時會初次生成,安裝新核心時又會重新生成。
grub.cfg 檔案包括了類似 Bash 指令碼的程式碼以及一個按照安裝順序排序的已安裝核心列表。例如,如果你有 4 個已安裝核心,最新的核心索引是 0,前一個核心索引是 1,最舊的核心索引是 3 。如果你能訪問 grub.cfg 檔案,你應該去看看感受一下它看起來是什麼樣。 grub.cfg 太大也就沒有包含在這篇文章中。
GRUB 配置檔案
grub.cfg 的主要配置檔案都在 /etc/grub.d 目錄。該目錄中的每個檔案都包含了最終會整合到 grub.cfg 檔案中的 GRUB 程式碼。這些配置檔案的命名模式以排序方式設計,這使得最終的 grub.cfg 檔案可以按正確的順序整合而成。每個檔案都有註釋表明該部分的開始和結束,這些註釋也是最終的 grub.cfg 檔案的一部分,從而可以看出每個部分是由哪個檔案生成。分隔註釋看起來像這樣:
### BEGIN /etc/grub.d/10_linux ###
### END /etc/grub.d/10_linux ###
不要修改這些檔案,除非你是一個 GRUB 專家並明白更改會發生什麼。無論如何,修改 grub.cfg 檔案時你也總應該保留一個原始檔案的備份。 40_custom 和 41_custom 這兩個特別的檔案用於生成使用者對 GRUB 配置的修改。你仍然要注意對這些檔案的更改的後果,並儲存一份原始 grub.cfg 檔案的備份。
你也可以把你自己的檔案新增到 /etc/grub.d 目錄。這樣做的一個可能的原因是為非 Linux 作業系統新增選單行。要注意遵循命名規則,確保配置檔案中額外的選單選項剛好在 10_linux 條目之前或之後。
GRUB 預設檔案
老版本 GRUB 的配置非常簡單而明瞭,我只需要修改 /boot/grub/grub.conf 就可以了。對於新版本的 GRUB2,我雖然還可以透過更改 /boot/grub2/grub.cfg 來修改,但和老版本的 GRUB 相比,新版本相對更加複雜。另外,安裝一個新核心時 grub.cfg 可能會被重寫,因此任何修改都可能消失。當然,GNU.org 的 GRUB 手冊確實有過直接建立和修改 /boot/grub2/grub.cfg 的討論。
一旦你明白瞭如何做,更改 GRUB2 配置就會變得非常簡單。我為之前的文章研究 GRUB2 的時候才明白這個。秘方就在 /etc/default 目錄裡面,一個自然而然稱為 grub 的檔案,它可以透過簡單的終端命令操作。/etc/default 目錄包括了一些類似 Google Chrome 、 useradd 、 和 grub 程式的配置檔案。
/etc/default/grub 檔案非常簡單。這個 grub 預設檔案已經列出了一些有效的鍵值對。你可以簡單地更改現有鍵值或者新增其它檔案中還沒有的鍵。下面的列表 1 顯示了一個沒有更改過的 /etc/default/grub 檔案。
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=”$(sed ‘s, release .*$,,g’
/etc/system-release)”
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT=“console”
GRUB_CMDLINE_LINUX=”rd.lvm.lv=fedora_fedora25vm/root
rd.lvm.lv=fedora_fedora25vm/swap
rd.lvm.lv=fedora_fedora25vm/usr rhgb quiet”
GRUB_DISABLE_RECOVERY=“true”
列表 1:Fedora 25 一個原始 grub 預設檔案。
GRUB 手冊 5.1 章節包括了所有可以新增到該 grub 檔案的鍵的資訊。我只需要修改 grub 預設檔案已經有的一些鍵值就夠了。讓我們看看這些鍵值以及一些在 grub 預設檔案中沒有出現的每個鍵的意義。
GRUB_TIMEOUT 這個鍵的值決定了顯示 GRUB 選擇選單的時間長度。 GRUB 提供了同時儲存多個安裝核心並在啟動時使用 GRUB 選單在其中選擇的功能。這個鍵的預設值是 5 秒,但我通常修改為 10 秒使得有更多時間檢視選項並作出選擇。
GRUB_DISTRIBUTOR 這個鍵定義了一個從 /etc/system-release 檔案中提取發行版本的 sed 表示式。這個資訊用於生成出現在 GRUB 選單中的每個核心釋出版的文字名稱,例如 “Fedora” 等。由於不同發行版之間 system-release 檔案結構的差異,在你的系統中這個 sed 表示式可能有些不同。
GRUB_DEFAULT 決定預設引導哪個核心。如果是 saved,這代表最新核心。這裡的其它選項如果是數字則代表了 grub.cfg 中列表的索引。使用索引號 3,就會總是載入列表中的第四個核心,即使安裝了一個新核心之後也是。因此使用索引數字的話,在安裝一個新核心後會載入不同的核心。要確保引導特定核心版本的唯一方法是設定 GRUB_DEFAULT 的值為想要核心的名稱,例如 4.8.13-300.fc25.x86_64 。
GRUB_SAVEDEFAULT 通常,grub 預設檔案中不會指定這個選項。當選擇不同核心進行引導時,正常操作下該核心只會啟動一次。預設核心不會改變。當其設定為 true 並和 GRUB_DEFAULT=saved 一起使用時,這個選項會儲存一個不同核心作為預設值。當選擇不同核心進行引導時會發生這種情況。
GRUB_DISABLE_SUBMENU 一些人可能會希望為 GRUB 選單建立一個核心的層級選單結構。這個鍵和 grub.cfg 中一些額外核心配置允許建立這樣的層級結構。例如,主選單中可能有 production 和 test 子選單,每個子選單中包括了一些合適的核心。設定它為 false 可以啟用子選單。
GRUB_TERMINAL_OUTPUT 一些環境下可能需要或者必要將輸出重定向到一個不同的顯示控制檯或者終端。預設情況下是把輸出傳送到預設終端,通常 console 等價於 Intel 系列個人電腦的標準輸出。另一個有用的選擇是在使用序列終端或者 Integrated Lights Out (ILO) 終端連線的資料中心或者實驗室環境中指定 serial 。
GRUB_TERMINAL_INPUT 和 GRUB_TERMINAL_OUTPUT 類似,可能需要或者必要重定向輸入為序列終端或者 ILO 裝置、而不是標準鍵盤輸入。
GRUB_CMDLINE_LINUX 這個鍵包括了在啟動時會傳遞給核心的命令列引數。注意這些引數會被新增到 grub.cfg 所有已安裝核心的核心行。這意味著所有已安裝的核心在啟動時都會有相同的引數。我通常刪除 rhgb 和 quiet 引數以便我可以看到引導和啟動時核心和 systemd 輸出的所有核心資訊訊息。
GRUB_DISABLE_RECOVERY 當這個鍵的值被設定為 false,GRUB 選單中就會為每個已安裝的核心建立一個恢復條目。當設定為 true 時就不會建立任何恢復條目。但不管這個設定怎樣,最後的核心條目總是一個 rescue 選項。不過在 rescue 選項中我遇到了一個問題,下面我會詳細介紹。
還有一些你可能覺得有用但我沒有在這裡介紹的鍵。它們的描述可以在 GRUB 手冊 2 的 5.1 章節找到。
生成 grub.cfg
完成所需的配置之後,就需要生成 /boot/grub2/grub.cfg 檔案。這透過下面的命令完成。
grub2-mkconfig > /boot/grub2/grub.cfg
這個命令按照順序使用位於 /etc/grub.d 的配置檔案構建 grub.cfg 檔案,然後使用 grub 預設檔案的內容修改輸出以便獲得最終所需的配置。 grub2-mkconfig 命令會嘗試定位所有已安裝的核心並在 grub.cfg 檔案的 10_Linux 部分新建條目。它還建立一個 rescue 條目提供一個用於從 Linux 不能啟動的嚴重問題中恢復的方法。
強烈建議你不要手動編輯 grub.cfg 檔案,因為任何對該檔案的直接修改都會在下一次安裝新核心或者手動執行 grub2-mkconfig 時被重寫。
問題
我遇到一個如果沒有意識到就可能導致嚴重後果的 GRUB2 問題。這個救援核心沒有啟動,反而啟動了另外一個核心。我發現那是列表中索引為 1 的核心,也就是列表中的第二個核心。額外的測試發現不管使用原始的還是我生成的 grub.cfg 配置檔案都會發生這個問題。我在虛擬機器和真實硬體上都嘗試過而且都發生了這個問題。我只測試了 Fedora 25,因此其它 Fedora 發行版本可能沒有這個問題。
注意,從救援核心生成的 “recovery” 核心條目不能引導到維護模式。
我推薦將 grub 預設檔案中 GRUB_DISABLE_RECOVERY 的值更改為 “false”,然後生成你自己的 grub.cfg 。這會在 GRUB 選單中為每個已安裝的核心生成可用的恢復條目。這些恢復配置能像期望那樣工作,從而從那些需要輸入密碼登入的核心條目中引導到執行級別 1,也就是進入 (不需要密碼的) 單使用者維護模式。你也可以按 Ctrl-D 繼續正常的引導進入預設執行級別。
總結
GRUB 是引導 Linux 計算機到可用狀態過程的一系列事件中,發生在 BIOS 之後的第一步。理解如何配置 GRUB 對於恢復或者處理多種型別的問題非常重要。
這麼多年來我多次不得不引導到恢復或者救援模式以便解決多種型別的問題。其中的一些問題確實是類似 /etc/fstab 或其它配置檔案中不恰當條目導致的引導問題,也有一些是由於應用程式或者系統站群軟體和最新的核心不相容的問題。硬體相容性問題也可能妨礙特定的核心啟動。