1. 程式人生 > >CentOS6啟動過程總結與GRUB問題修復

CentOS6啟動過程總結與GRUB問題修復

轉載地址:https://www.2cto.com/net/201609/549564.html

一、CentOS 6 的啟動流程

第一步:加電自檢(POST)

主要檢查硬體裝置是否存在並能正常執行,如:CPU、記憶體、硬碟、風扇、輸入輸出裝置等。自檢功能主要是通過BIOS來實現的,BIOS程式是裝載在一個硬體晶片CMOS上的,加電過程就是給CMOS通電,然後啟動BIOS程式,BIOS程式會根據CMOS上面的一些配置資訊區讀取其他的硬體裝置資訊並檢測其是否存在並能正常執行,之後進行硬體裝置的初始化。

第二步:選擇啟動順序,載入MBR

按照BIOS中設定的Boot Sequence查詢Boot Loader程式所在的裝置。Boot Loader是一個程式,它依賴於一個硬體之上,這個硬體就是硬碟,準確的說為第一個可以啟動的硬碟的第一個扇區內,即MBR(Master Boot Record,主引導記錄)。

Boot Loader的主要功能就是去識別、載入操作系統中的核心檔案,並提交到記憶體中執行,進而來啟動對應的作業系統。另一個主要功能是提供選單資訊(可以提供不同的啟動項來載入不同的作業系統),並將啟動管理功能轉交給其他的載入程式。

第三步:載入系統核心(Kernel)檔案,執行系統初始化資訊

Boot Loader程式讀取作業系統的核心檔案後,會將其解壓後裝載到記憶體當中,然後接管BIOS的工作開始測試並載入各個裝置(CPU、硬碟、網絡卡等)。

因為核心檔案(Kernel)通常是存放在系統上的/boot目錄中,並且是以vmlinuz開頭的檔案,此時記憶體程式還沒有載入到硬碟,因此無法讀取系統上的核心檔案,而如果先去載入硬碟則必須有硬碟的驅動程式,因此這將會產生一個先後順序的問題,為了解決這個問題,

Linux採用GRUB啟動管理程式來識別硬碟資訊,RTUB程式的執行過程需要三個階段,具體的執行過程將在下面的第二章節介紹。

第四步:啟動第一個執行程式/sbin/init

在核心、硬體及驅動資訊載入完畢後,核心會呼叫使用者控制元件的第一個執行程式/sbin/init,init程式主要功能是準備軟體執行環境,包括系統的主機名稱、網路配置、檔案系統格式等其他服務的啟動管理。而這些所有的操作都是通過init的配置檔案來定義的。

在CentOS 5 中 init 的配置檔案為:/etc/inittab

在CentOS 6 中 init 的配置檔案為:/etc/inittab,/etc/init/*.conf

在init的配置檔案中有個一非常重要的配置專案,那就是預設的系統啟動級別。啟動級別是為系統維護的目的而設定的,其實現方式是關閉或啟動對應級別下的服務。以下為init的7個執行級別:

0:halt,關機

1:Single user,單使用者模式,此級別允許以root使用者身份登入,而無需認證,相當於windows的安全模式

2:Multiuser,多使用者模式,需要使用者認證,會啟動網路功能,但不會啟動NFS

3:Full multiuser,完全多使用者模式,文字介面

4:unused,預留級別,目前無特別的使用目的

5:X11,正常級別,也是完全多使用者模式,圖形介面

6:reboot,重啟

通常使用較多的預設級別為3或5,伺服器上一般預設使用3級別,不同級別之間是可以進行切換的,切換方式為:init [0-6],可以使用 who -r或run_leave命令檢視執行級別。

第五步:執行系統初始化指令碼

根據 init 的配置檔案,先獲取預設的 runlevel,然後再執行 /etc/rc.d/rc.sysinit 指令碼完成系統初始化。

系統初始化指令碼所做的事情主要有:

1、設定主機名(讀取/etc/sysconfig/network檔案)

2、啟用 SELinux 和 udev

3、列印文字歡迎資訊

4、掛載所有定義在/etc/fstab檔案中的檔案系統

5、啟用 swap 裝置

6、檢測跟檔案系統,並實現以讀寫方式重新掛載

7、設定系統時鐘

8、根據 /etc/sysctl.conf 檔案設定核心引數的值

9、啟用LVM和RAID裝置

10、載入額外的裝置驅動程式

11、清理操作

第六步:啟動系統服務

按照預設級別的引數N,執行 /etc/rcN.d/ 目錄下設定的關閉和啟動相應的服務。

第七步:列印登入提示符

二、GRUB程式的三個階段

stage1:執行Boot Loader主程式,這個程式必須要被安裝在啟動區(MBR)。因為MBR空間有限,因此在MBR當中僅安裝Boot Loader的最小主程式,並沒有安裝Boot Loader的相關配置檔案。

stage1_5:存放在MBR隨後的扇區中,主要用於與stage2所在分割槽的檔案系統進行互動。

stage2:通過Boot Loader載入所有配置檔案及相關的環境引數資訊,這些配置檔案及相關的環境引數都存放於磁碟分割槽上的/boot目錄下。

grup的配置檔案路徑為:/boot/grub/grub.conf,內容如下:

default:設定預設啟動的核心和作業系統,如果同時安裝了多個作業系統或核心,0表示定義的第一個title系統,1表示定義的第二個title系統,依次類推;

timeout:設定系統啟動時選擇作業系統選單的等待時間,單位是秒(s);

splashimage:設定系統啟動時grub選單的背景圖片。圖片格式為xpm,14bits顏色,大小為640*480,需要gzip壓縮;

hiddenmenu:隱藏選擇選單,預設情況下是不顯示選單資訊,如果想要顯示選單,將該配置註釋即可;

title:定義一個作業系統或系統核心,且包括下面內容:

root:指明引導當前作業系統或核心檔案所在的分割槽;

kernel:指定檔案路徑、根檔案系統所在裝置,以及傳遞給核心的引數。由於啟動過程中需要掛載跟目錄,因此需要指定根目錄所在的分割槽。核心引數 rhgb表示色彩顯示,quiet表示靜默模式載入核心;

initrd:指定用於輔助核心完成系統啟動的ramdisk檔案路徑;

三、關於GRUB的除錯

1、破解root使用者密碼

第一步:系統啟動時按任意鍵進入GRUB選單,動作一定要快,預設是5s的倒計時

如上圖所示,可以使用上下鍵選擇要啟動的作業系統(這裡只用一個);

按“e”可以對選擇的項進行編輯;

按“a”可以對選擇的項進行核心引數修改;

按“c”可以進入命令列模式;

第二步:根據提示,選擇相應的選單,然後按“a”,在原有核心引數的最後加上“1或s或S或single”的任意一個引數,表示進入單使用者模式,然後按回車鍵啟動系統

第三步:以單使用者模式進入系統後,使用passwd命令修改root使用者密碼,修改完之後重啟系統即可使用新的root使用者密碼登入系統。

2、為GRUB選單設定保護密碼

預設情況下進入GRUB選單後不需要任何密碼就可以進行編輯,相對來說是比較危險的,因此可以修改 grub.conf 配置檔案為GRUB選單設定密碼保護,在 grub.conf 檔案中的title欄位上面新增一行pwssword PASSWD,password支援命令口令和加密口令,具體設定如下圖所示:

md5加密口令的生成命令為:grub-md5-crypt

在grub.conf檔案中新增password後,再次進入GRUB選單時如果想要編輯則必須按“p”鍵,然後通過密碼驗證後才能編輯,如下圖所示:

同理,在grub.conf 配置檔案中的title內新增password,可以保護核心,即進入系統時需要輸入密碼驗證後才能啟動。

3、取消圖形介面的啟動,使用文字介面啟動

系統預設的啟動方式是圖形介面啟動,因此看不到系統的啟動過程,可以通過修改 grub.conf 配置檔案設定成文字介面啟動,生產環境下也建議使用文字介面啟動,因為這種啟動方式可以看到整個過程,如果哪個服務在啟動過程中出錯可以及時發現。修改方法是把kernel引數中的rhgb和quiet刪除。

4、如果/boot下的檔案損壞或丟失的恢復方法

第一步:使用安裝光碟進入救援模式,進入時需要根據提示手動選擇語言、鍵盤等

載入救援模式的過程中會提示硬碟上的系統已經被找到並掛載到/mnt/sysimage下,因此進入救援模式後可以使用 chroot /mnt/sysimage 命令切換到硬碟上作業系統的根目錄下,因為救援模式下提供的命令比較有限,好多命令都不支援。

如果進入到救援模式後,沒有發現硬碟上的根檔案系統,則需要使用相關命令查詢並分析根檔案系統所在硬碟分割槽位置,如果硬碟使用的是普通分割槽,則可以通過 blkid 命令和 fdisk -l 命令分析出根檔案系統的分割槽位置,而如果硬碟使用的是LVM分割槽,則可以使用 lvscan 命令檢視分割槽,並且需要使用 vgchange -ay 命令啟用VG卷組。

分析出根檔案系統所在分割槽後掛載根檔案系統,然後檢查並修改fstab檔案,如果該檔案丟失,則手動建立一份,按照相應格式在其中添加掛載根檔案系統的條目,然後重啟系統,直到能夠自動檢測出硬碟上的系統並掛載到/mnt/sysimage下為止。

第二步:進入到硬碟的根檔案系統後,使用mount命令掛載光碟,比如將光碟掛載到/mnt/cdrom上:

第三步:使用rpm命令安裝kernel包,安裝時會提示kernel已安裝,需要使用--force或--replacepkgs選項強制安裝。安裝完之後會在/boot目錄下自動生成initramfs檔案和vmlinuz檔案

vmlinuz-2.6.32-642.el6.x86_64 和 initramfs-2.6.32-642.el6.x86_64.img 是系統啟動時必要的兩個檔案,缺一不可。

vmlinuz-2.6.32-642.el6.x86_64:核心檔案,如果只是該檔案丟失,可以從光碟或者相同版本的作業系統上拷貝。

initramfs-2.6.32-642.el6.x86_64.img:虛擬檔案系統,通過Boot Loader程式能夠將其載入到記憶體中,然後這個檔案會被解壓縮並且在記憶體中模擬一個跟檔案系統,這個跟檔案系統能夠提供一個可以執行的程式,通過該程式可以載入在啟動過程中所需要的核心模組(RAID、LVM、SCSI等檔案系統與磁碟的驅動程式),載入完成之後,會協助核心重新呼叫/sbin/init來執行後續的正常啟動。如果只是該檔案丟失,可以使用 mkinitrd /boot/initramfs-`uname -r`.img `uname -r` 重新生成 。

第四步:使用 grub-install 命令修復grub,需要注意的是該命令需要指定/boot目錄的父目錄,如果/boot的父目錄是根目錄(/),則可以省略 --root-directory=DIR 選項。該命令也可以修復/boot/grub下的檔案

第五步:在/boot/grub下建立 grub.conf 配置檔案,配置檔案內容如下圖所示

第六步:使用exit命令退出硬碟中的檔案系統,再使用reboot命令重啟系統

5、grub.conf檔案損壞的修復

如果grub.conf檔案損壞,則作業系統將不能正常啟動,此時手中如果有安裝光碟的話可以通過救援模式重新建立grub.conf檔案,但如果沒有安裝光碟的話,可以通過以下方式修復:

第一步:如果grub.conf檔案損壞,則系統系統時會自動進入grub的命令列模式,該模式下可以通過 help 命令檢視幫助。使用root命令可以顯示當前grub所在硬碟的分割槽位置;

第二步:使用 root 命令指定核心存放的位置;

第三步:使用 kernel 命令設定kernel檔案路徑及根檔案系統所在裝置,支援Tab命令補全;

第四步:使用 initrd 命令設定initramfs路徑,支援Tab命令補全;

第五步:使用 boot 命令啟動系統;

第六步:系統啟動後手工重新編寫 /boot/grub/grub.conf 配置檔案。

四、在U盤上自制 Linux 系統

根據 CentOS 6 的啟動過程,可以在U盤上自制一個定製版的Linux系統,首先需要劃分出一個/boot分割槽和一個根(/)分割槽,其次需要安裝grub,然後將核心檔案和initramfs檔案放入到U盤的/boot目錄下,最後建立必要的配置檔案,具體步驟如下:

第一步:使用 fdisk 命令為U盤建立/boot分割槽和根分割槽,/boot分割槽(/dev/sdb1)大小為100M,根分割槽(/dev/sdb2)大小為6G

第二步:格式化分割槽,將/boot分割槽(/dev/sdb1)和根分割槽(/dev/sdb2)都格式化成ext4格式

第三步:分別將U盤上的boot(/dev/sdb1)分割槽和根分割槽(/dev/sdb2)掛載到當前系統的/mnt/boot和/mnt/sysroot上

第四步:使用 grub-install 命令安裝grub,注意需要指定所掛載U盤/boot分割槽的父目錄為/mnt

第五步:在/mnt/boot/grub目錄下建立grub.conf配置檔案,該配置檔案中需要在kernel引數配置項中關閉selinux,並指定init程式為/bin/bash

第六步:複製核心檔案和initramfs檔案到/mnt/boot目錄下

第七步:在/mnt/sysroot目錄下建立一級目錄

第八步:在/mnt/sysroot/bin目錄下建立fstab的自動掛載檔案

第九步:複製bash命令及相關庫檔案,注意bash命令和庫檔案的路徑一定要放對,可以使用which命令檢視bash路徑,使用ldd命令檢視bash的依賴庫。

第十步:參考第九步,根據需求複製相應的命令及庫檔案,可以使用指令碼複製命令和庫,指令碼內容如下:

[[email protected]~]#catcopycmd.sh

#!/bin/bash

ch_root="/mnt/sysroot"

[!-d$ch_root]&&mkdir$ch_root

bincopy(){

ifwhich$1&>/dev/null;then

localcmd_path=`which--skip-alias$1`

localbin_dir=`dirname$cmd_path`

[-d${ch_root}${bin_dir}]||mkdir-p${ch_root}${bin_dir}

[-f${ch_root}${cmd_path}]||cp-n$cmd_path${ch_root}${bin_dir}

return0

else

echo"Commandnotfound."

return1

fi

}

libcopy(){

locallib_list=$(ldd`which--skip-alias$1`|grep-Eo'/[^[:space:]]+')

forloopin$lib_list;do

locallib_dir=`dirname$loop`

[-d${ch_root}${lib_dir}]||mkdir-p${ch_root}${lib_dir}

[-f${ch_root}${loop}]||cp-n$loop${ch_root}${lib_dir}

done

}

read-p"Pleaseinputacommand:"command

while["$command"!="quit"];do

ifbincopy$command;then

libcopy$command

fi

read-p"Pleaseinputacommandorquit:"command

done