Linux學習-Boot Loader: Grub2


boot loader 的兩個 stage

在 BIOS 讀完信息后,接下來就是會到第一個開機裝置 的 MBR 去讀取 boot loader 了。這個 boot loader 可以具有選單功能、直接加載核心文件以及控制權 移交的功能等, 系統必須要有 loader 才有辦法加載該操作系統的核心就是了。但是我們都知道, MBR 是整個硬盤的第一個 sector 內的一個區塊,充其量整個大小也才 446 bytes 而已。我們的 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 的配置文件 /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 模式

注意幾個東西即可,那就是:

  • 硬盤代號以小括號 ( ) 包起來;
  • 硬盤以 hd 表示,后面會接一組數字;
  • 以『搜尋順序』做為硬盤的編號!(這個重要!)
  • 第一個搜尋到的硬盤為 0 號,第二個為 1 號,以此類推;
  • 每顆硬盤的第一個 partition 代號為 1 ,依序類推。

所以說,第一顆『搜尋到的硬盤』代號為:『(hd0)』,而該顆硬盤的第一號分區槽為『(hd0,1)』,另外,為了區分不同的分區格式,因此磁盤后面的分區號碼可以使用類似 msdos1 與 gpt1 的方式來調整! 最終要記得的是,磁盤的號碼是由 0 開始編號,分區槽的號碼則與 Linux 一 樣,是由 1 號開始編號!

所以說,整個硬盤代號為:

硬盤搜尋順序 在 Grub2 當中的代號
第一顆(MBR) (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3)....
第二顆(GPT) (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3)....
第三顆 (hd2) (hd2,1) (hd2,2) (hd2,3)....

  • /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 的, 也就是說,鳥哥的測試機在開機的時候應該就會有兩個可以選擇的選單的意思啰!

在 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 』 那個項目的裝置, 才會得到正確的位置喔!注意注意!

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
[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"     # 取消救援選單的制作
  • 倒數時間參數: GRUB_TIMEOUT

這個設定值相當簡單,后面就是接你要倒數的秒數即可~例如要等待 30 秒,就在這邊改成 『GRUB_TIMEOUT=30』即可!如果不想等待則輸入 0 , 如果一定要使用者選擇,則填 -1 即可!

  • 是否隱藏選單項目:GRUB_TIMEOUT_STYLE

這個項目可選擇的設定值有 menu, countdown, hidden 等等。如果沒有設定,預設是 menu 的意思。 這個項目主要是在設定要不要顯示選單! 如果你不想要讓使用者看到選單,這里可以設定為 countdown!那 countdown 與 hidden 有啥差異呢?countdown 會在屏幕上顯示剩余的等待秒數, 而 hidden 則空空如也~

  • 訊息輸出的終端機模式:GRUB_TERMINAL_OUTPUT

這個項目是指定輸出的畫面應該使用哪一個終端機來顯示的意思,主要的設定值有『 console, serial,gfxterm, vga_text 』等等。

  • 默認開機選單項目: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
  • 核心的外加參數功能:GRUB_CMDLINE_LINUX

如果你的核心在啟動的時候還需要加入額外的參數,就在這里加入吧!舉例來說,如果你除了預 設的核心參數之外,還需要讓你的磁盤讀寫機制為 deadline 這個機制時, 可以這樣處理:

GRUB_CMDLINE_LINUX="..... crashkernel=auto rhgb quiet

這個主要環境配置文件編寫完畢之后,必須要使用 grub2-mkconfig 來重建 grub.cfg 才行喔!因為主 配置文件就是 grub.cfg 而已, 我們是透過許多腳本的協力來完成 grub.cfg 的自動建置。當然啰, 額外自己設定的項目,就是寫入 /etc/default/grub 文件內就是了。


  • 選單建置的腳本 /etc/grub.d/*

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 的功能啦!常見的有這幾樣:

  • 直接指定核心開機

基本上如果是 Linux 的核心要直接被用來開機,那么你應該要透過 grub2-mkconfig 去抓 10_linux 這個腳本直接制作即可,基本上如果是 Linux 的核心要直接被用來開機,那么你應該要透過 grub2-mkconfig 去抓 10_linux 這個腳本直接制作即可,因此這個部份你不太需要記憶! 因為在 grub.cfg 當中就已經 是系統能夠捉到的正確的核心開機選單了!不過如果你有比較特別的參數需要進行呢?這時候你 可以這樣作: (1)先到 grub.cfg 當中取得你要制作的那個核心的選單項目,然后將它復制到 40_custom 當中 (2)再到 40_custom 當中依據你的需求修改即可。

  • 透過 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 軟件讀出來的意思!
}

initramfs 的重要性與建立新 initramfs 文件

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 認識的文件系統時;
  • 其他必須要在核心加載時提供的模塊。

一般來說,各 distribution 提供的核心都會附上 initramfs 文件,但如果妳有特殊需要所以想重制 initramfs 文件的話, 可以使用 dracut / mkinitrd 來處理的。這個文件的處理方式很簡單, man dracut 或 man mkinitrd 就知道了。 CentOS 7 應該要使用 dracut 才對,不過 mkinitrd 還是有保留 下來,兩者隨便你玩!鳥哥這里主要是介紹 dracut 就是了!

[root@study ~]# dracut [-fv] [--add-drivers 列表] initramfs 檔名 核心版本
選項與參數:
-f :強迫編譯出 initramfs ,如果 initramfs 文件已經存在,則覆蓋掉舊文件
-v :顯示 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 當中了呢!很愉快喔!

測試與安裝 grub2

如果你的 Linux 主機本來就是使用 grub2 作為 loader 的話,那么你就不需要重新安裝 grub2 了, 因為 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 去抓設定嗎? 如果是多重操作系統那怎辦? 呵呵!這就需要重新進入新系統才能夠安裝啦!

最后總結一下:

  1. 如果是從其他 boot loader 轉成 grub2 時,得先使用 grub2-install 安裝 grub2 配置文件;
  2. 承上,如果安裝到 partition 時,可能需要加上額外的許多參數才能夠順利安裝上去!
  3. 開始編輯 /etc/default/grub 及 /etc/grub.d/* 這幾個重要的配置文件;
  4. 使用 grub2-mkconfig -o /boot/grub2/grub.cfg 來建立開機的配置文件!

關於開機畫面與終端機畫面的圖形顯示方式

如果你想要讓你的開機畫面使用圖形顯示方式,例如使用中文來顯示你的畫面啊!因為我們預設的 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

為個別選單加上密碼

grub2 控制有:(1)grub2 的選單指令列修改與 (2)進入選擇的選單開機流程。


  • grub2 的賬號、密碼與選單設定

grub2 有點在模擬 Linux 的賬號管理方案喔!因為在 grub2 的選單管理中,有針對兩種身份進行密 碼設定:

  • superusers: 設定系統管理員與相關參數還有密碼等,使用這個密碼的用戶,將可在 grub2 內具有所有修 改的權限。 但一旦設定了這個 superusers 的參數,則所有的指令修改將會被變成受限制的!

  • users: 設定一般賬號的相關參數與密碼,可以設定多個用戶喔!使用這個密碼的用戶可以選擇要進入某些 選單項目。 不過,選單項目也得要搭配相對的賬號才行喔!(一般來說,使用這種密碼的賬號並不能修改選 單的內容,僅能選擇進入選單去開機而已)

這樣說可能你不是很容易看得懂,我們使用底下的一個范例來說明你就知道怎么處理了。另外,底下 的范例是單純給讀者們看看而已的~ 不能夠直接用在我們的測試機器里面喔!

假設你的系統有三個各別的操作系統,分別安裝在 (hd0,1), (hd0,2), (hd0,3) 當中。假設 (hd0,1) 是所有人都可以選 擇進入的系統, (hd0,2) 是只有系統管理員可以進入的系統,(hd0,3)則是另一個一般用戶與系統管理員可以進入的 系統。另外,假設系統管理員的賬號/密碼設定為 vbird/abcd1234, 而一般賬號為 dmtsai/dcba4321 ,那該如何設 定?

# 第一個部份是先設定好管理員與一般賬號的賬號名稱與密碼項目!

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 這個管理員賬號!


  • 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

  • 為個別的選單設定賬號密碼的使用模式

回想一下我們之前的設定,目前測試機器的 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM