- CentOS 6啟動流程
- CentOS 5,6的init啟動過程詳解
- grub啟動過程詳解
- 啟動過程錯誤修復
一、CentOS 6啟動流程
(一)Linux組成
-
linux由kernel和rootfs組成:
- kernel:進程管理、內存管理、網絡管理、驅動程序、文件系統、安全功能
- rootfs:包含程序和庫(glibc)
-
內核涉及流派:
- 單內核(monolithic kernel):所有功能集成于一個程序,如linux
- 微內核(micro kernel):每種功能由單獨子系統實現,如Windows
-
linux內核特點:
- 模塊化設計:體現為眾多的.ko文件(內核模塊文件),實現文件系統、硬件驅動、網絡協議等kernel功能
- 可以動態裝載、卸載內核模塊
-
linux內核組成
- 核心文件:/boot/vmlinuz-version-release
- 輔助的偽根系統ramdisk(系統啟動時非常重要):
/boot/initrd-VERSION-release.img (CentOS 5)
/boot/initramfs-VERSION-release.img (CentOS 6, 7) - 模塊文件:
/lib/modules/version-release目錄下
(二)CentOS 6啟動流程概述
大致流程:POST加電自檢-->MBR引導-->GRUB-->加載內核-->啟動init進程-->按照配置文件描述運行相應腳本
-
第1步 POST(Power-On-Self-Test):加電自檢
運行BIOS的自檢程序,完成硬件系統的檢測。隨后按照BIOS設置的啟動順序查找第一個有引導程序的設備為本次啟動設備,將設備管理權限移交給啟動設備上的引導程序。
-
第2步 bootloader:引導程序
位于MBR的前446字節,允許用戶選擇啟動的系統或內核版本,裝載、運行內核并把管理權限移交給內核程序。目前linux使用的主流bootloader為GRUB(CentOS 6使用GRUB 0.9, CentOS 7使用GRUB 2)
-
第3步 GRUB的分階段引導
由于MBR給bootloader預留的空間太狹小,GRUB程序分布在硬盤的多個位置
primary bootloader:1st stage(位于MBR的前446字節), 1.5 stage(識別/boot分區類型并加載相應的驅動)
secondary bootloader:2nd stage(位于/boot/grub,顯示啟動菜單和用戶交互程序,負責內核加載,并將管理權移交給內核)
-
第4步 內核自身初始化
探測硬件設備
-
在ramdisk提供基本驅動(只用于滿足啟動使用)的前提下,加載各硬件驅動
- ramdisk管理工具:mkinitrd(CentOS 6), dracut(CentOS 7)
以只讀方式掛載根文件系統
實驗:為當前正在使用的內核重新制作啟動文件
mkinitrd /boot/initramfs-`uname -r`.img `uname -r`
或者
dracut /boot/initramfs-`uname -r`.img `uname -r`
刪除/boot目錄下的initramfs文件
重啟后進入系統失敗,進入救援模式,先使用chroot命令切換根目錄,重建initramfs文件,重啟后正常進入系統
- 第5步 運行用戶空間第一個應用程序/sbin/init,啟動相關服務
二、CentOS 5,6的init啟動過程詳解
(一)init程序類型
啟動程序 | 進程名稱 | 應用版本 | 配置文件 |
---|---|---|---|
SysV | init | CentOS 5之前 | /etc/inittab |
Upstart | init | CentOS 6 | /etc/inittab, /etc/init/*.conf |
Systemd | systemd | CentOS 7 | /usr/lib/systemd/system, /etc/systemd/system |
(二)運行級別
-
定義:為系統運行和維護目的而設定,共有0-6共7個級別
- 0:關機
- 1:單用戶模式,root自動登錄,可用于重置root密碼
- 2:不完全的多用戶模式,啟用網絡功能,但不啟用NFS
- 3:完全的多用戶模式
- 4:預留
- 5:圖形界面模式
- 6:重啟
默認的運行級別:/etc/inittab中設置,一般設為3或者5,不能設置為0或者6
修改運行級別:
init LEVEL
,LEVEL取值為0-6查看運行級別:
runlevel
或who -r
實驗:忘記root密碼時重置root密碼
啟動時,在bootloader啟動倒計時鍵盤任意鍵進入啟動項管理頁面
按提示輸入a,在提示的畫面字符串后輸入1,代表進入runlevel: 1的單用戶模式
無需輸入密碼,即可進入root賬戶,此時可以重置root密碼
(三)CentOS 5和6的/etc/inittab文件
-
CentOS 5的/etc/inittab文件:
- 內容:文件的每一行定義一個action和與其對應的process
- 格式:
id:runlevel:action:process
說明:
id:僅起到標識作用
runlevel:運行級別
action:
(1) wait:切換至此級別運行一次
(2) respawn:若process終止,則重新運行它,一般在mingetty時使用
如:1:2345:respawn:/usr/sbin/mingettytty1
,這樣結束mingetty1進程后會自動產生新的mingetty進程,保證有足夠終端供人使用
(3) initdefault:設定為默認運行級別,process省略
(4) sysinit:設定系統初始化方式,一般process設為/etc/rc.d/rc.sysinit
CentOS 6的/etc/inittab文件和相關文件
CentOS 6的/etc/inittab文件只保留了設定默認運行級別的語句,其他內容被移動到/etc/init/*.conf各類設置文件中
(四)CentOS 5的init啟動流程
(1)運行/etc/rc.d/rc.sysinit系統初始化腳本
- 主要功能:
(1) 設置主機名
(2) 設置歡迎信息
(3) 激活udev和selinux
(4) 掛載/etc/fstab文件中定義的文件系統
(5) 檢測根文件系統,并以讀寫方式重新掛載根文件系統
(6) 設置系統時鐘
(7) 激活swap設備
(8) 根據/etc/sysctl.conf文件設置內核參數
(9) 激活lvm及software raid設備
(10) 加載額外設備的驅動程序
(11) 清理操作
(2)按照/etc/inittab文件規定的默認運行級別,運行相應級別的/etc/rc.d/rcN.d(N為運行級別)目錄下的文件
-
/etc/rc.d/rcN.d文件格式:
- rcN.d下的文件均為指向/etc/rc.d/init.d目錄下服務的軟鏈接文件
- 軟鏈接的命名格式:K##或者S##
- S表示運行時開啟服務,K表示運行時關閉服務
- ##代表運行順序,排序越靠前,越先運行。排序方式為依次對比相同位置的數字字母,數字小于字母
如:100比99靠前,因為從第1位比較1比9靠前
又如:99比9a靠前,因為第1位相同,比較第2位9比a靠前 - 以K開頭的服務越靠前,代表服務越依賴于其他服務,因為只有先停止本服務,被依賴的服務才能停止
- 以S開頭的服務越靠前,代表服務越被其他服務所依賴,因為只有先開啟本服務,依賴其運行的服務才能開啟
- /etc/rc.d/rc{2,3,4,5}.d目錄下最后啟動的服務均為S99local,此鏈接文件鏈指向/etc/rc.d/rc.local腳本,rc.local腳本不是服務。當需要開機執行一些指令,又不想在/etc/rc.d/init.d目錄下專門寫一個服務腳本時,可以在本腳本文件中定義。
chkconfig命令:設置服務在所有運行級別的開啟、關閉情況,語法設置如下:
chkconfig [--list] [service_name] //查詢服務
chkconfig --add service_name //添加服務
chkconfig --del service_name //刪除服務
chkconfig --levle LLLL sevice_name <on|off|reset>
//修改服務,指定的運行級別--level LLLL省略時默認為2345
chkconfig實質是修改/etc/rc.d/rcN.d目錄下文件前綴K或S,如下圖所示,關閉atd在runlevel 5級別下啟動后,在/etc/rc.d/rc5.d目錄下以S開頭的atd文件消失,而以K開頭的atd文件出現,同時可以看到S靠后的服務往往K靠前,反之亦然,證明先啟動的服務需要后退出,而后啟動的服務需要先退出
刪除/etc/rc.d/rc5.d下的K05atd軟鏈接后,手動建立S95atd軟鏈接,使用chkconfig查詢發現已經變成了on,進一步印證chkconfig的工作原理
- ntsysv:改變運行級別服務的開啟、關閉情況
ntsysv [--level=RUN_LEVEL],默認修改當前運行級別
- 實驗:創建一個自定義服務S97serv,添加、修改、刪除服務
第1步,在/etc/rc.d/init.d目錄下,新建服務腳本文件
#! /bin/bash
# checkconfig: 35 96 07 //表示在runlevel=3, 5時開啟服務,在/etc/rc.d/rc3.d和/etc/rc.d/rc5.d目錄下的軟鏈接文件名前綴為S96和K07
# description: //本描述內容在CentOS 5中必須有,在CentOS 6中可以有
腳本內容略
第2步,chkconfig命令添加此服務,查詢此服務在各個運行級別的開啟、關閉狀態是否符合服務腳本文件中的描述
第3步,chkconfig修改此服務在運行級別3的狀態為off
第4步,chkconfig刪除此服務
-
service命令:手動管理服務
- 語法:
service service_name start|stop|restart|status
,服務開啟、關閉、重啟、狀態查詢
service --status-all
,查詢所有服務的狀態
- 語法:
-
xinetd管理的服務:
- xinetd管理非獨立服務(又稱瞬態服務),這些服務的使用率不高,為了節省資源占用,平時xinetd服務負責監聽這些服務的端口,一旦xinetd服務發現其所管理服務的請求,立即喚醒相應的服務,并將相應服務的端口移交給服務
- xinetd管理很多服務,所以又稱其為超級守護進程
- 非獨立服務依賴于xinetd服務,若xinetd服務尚未安裝,則安裝非獨立服務時xinetd作為依賴服務將一并安裝
- 配置文件:/etc/xinetd.conf, /etc/xinetd.d/<service>
-
實驗:開啟Telnet服務
第1步,chkconfig --list命令發現telnet服務屬于非獨立服務,需要修改xinetd服務的配置文件第2步,配置/etc/xinetd.d/telnet,將disabled的值由yes改為no,重新執行chkconfig --list命令,發現telnet的狀態已經變成yes
第3步,重啟xinetd服務,此時通過
netstat -ntlp
查看監聽端口,發現xinetd正在監聽telnet的23端口第4步,遠程telnet登錄本機,此時通過
ss -ntup
查看tcp端口,發現telnet正在23端口處于連接狀態
(3)按照/etc/inittab文件的規定,設置登錄終端
CentOS 5 init啟動順序總結:
- 運行/sbin/init,創建用戶空間第一個進程-->
- 查詢/etc/inittab初始化配置文件,設置默認運行級別-->
- 運行/etc/rc.d/rc.sysinit系統初始腳本、完成系統初始化-->
- 關閉(可能出現)對應下需要關閉的服務,啟動需要啟動服務/etc/rc.d/rcN.d-->
- 設置登錄終端
- CentOS 6的啟動過程與CentOS 5基本相似,區別在于CentOS 6的init啟動過程配置文件為/etc/inittab和/etc/init/*.conf,遵循upstart程序規定的配置文件語法格式
三、grub啟動過程詳解
(一)grub簡介
版本:
grub 0.97: CentOS 6使用,grub經典版,以下介紹的都是此版本的操作
grub 2:CentOS 7開始使用-
grub的階段:grub程序分布在硬盤的不同位置,被分為多個階段
- stage 1:bootloader,位于MBR,446字節
- stage 1_5:位于MBR之后的扇區,確保stage1的bootloader能夠識別stage2所在分區的文件系統
- stage 2:
1)顯示啟動菜單,實現與用戶的交互
2)加載用戶選擇的內核或操作系統
3)為菜單提供了保護機制
stage 2 和內核文件一般安裝至一個基本的磁盤分區(/boot一般是獨立分區)
grub安裝:grub-install命令
將stage 1和stage 1_5安裝至啟動硬盤,并復制grub相關文件至啟動硬盤的啟動分區
(二)grub的詳細配置
(1) grub命令行模式:
-
命令:
- help:獲取幫助列表
- help KEYWORD:詳細幫助信息
- root (hd#,#):指定grub的根分區,即stage2文件和內核文件所在的分區
- kernel /PATH/TO/KERNEL_FILE:設定本次啟動時用到的內核文件;額外還可添加許多內核支持使用的cmdline參數,可通過
cat /proc/cmdline
查詢內核參數 - initrd /PATH/TO/INITRAMFS_FILE:設定為選定的內核提供額外文件的ramdisk
- boot:引導啟動選定的內核
-
硬盤分區編號規則(hd#,#):
- hd#:磁盤編號,用數字表示;從0開始編號
- #:分區編號,用數字表示; 從0開始編號
- (hd0,0) 表示第一塊硬盤,第一個分區
-
手動通過grub命令行啟動系統:
grub> root (hd#,#) grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE grub> initrd /initramfs-VERSION-RELEASE.img grub> boot
(2)grub配置文件 /boot/grub/grub.conf:
格式:
通用設置
default=#:默認啟動菜單項,從0開始編號
timeout=#:自動進入默認啟動菜單項的倒計時
splashimage=(hd#,#)/PATH/XPM_FILE:菜單界面背景圖片
hiddenmenu:默認隱藏啟動菜單
password [-md5|] string:啟動菜單編輯認證
以下是關于菜單項的設置,可以重復使用多次用于設置多個菜單項
title TITLE:菜單項標題
root (hd#,#):指定grub的根分區,即stage2文件和內核文件所在的分區
kernel /PATH/TO/VMLINUZ_FILE:指定kernel文件的路徑
initrd /PATH/TO/INITRAMFS_FILE:指定內核匹配的initramfs文件路徑
password [-md5 | encrypted] string:啟動選定內核或操作系統時認證生成grub密碼:
grub-md5-crypt:生成md5加密密碼
grub-crypt:生成sha512加密密碼實驗:/boot/grub/grub.conf文件格式要求
實驗(1):判斷kernel行和initrd行可否交換次序:
在/boot/grub/grub.conf文件中復制當前啟動菜單選項設置,交換kernel行和initrd行的次序
重啟系統,進入復制的啟動項,發現錯誤提示:kernel必須在initrd前
按任意鍵回到啟動菜單,鍵盤輸入e后編輯啟動項,綜合使用鍵盤d:刪除,鍵盤e:編輯,鍵盤o:新增加空行,將kernel行與initrd行交換次序,鍵盤b執行啟動,最終成功啟動
由于本次啟動屬于在grub中臨時更改啟動項,在系統啟動之后,需要及時對/boot/grub/grub.conf文件進行修改,確保今后啟動正常
實驗(2):給grub的啟動過程加密:
可以在grub的啟動過程的兩個環節加密:1)給啟動菜單項編輯權限加密;2)啟動特定菜單項的加密,加密命令相同,但是位于/boot/grub/grub.conf文件的不同位置
加密可以使用明文密碼,但安全性太差。目前使用md5和sha-512加密方式加密,現在用md5加密啟動項編輯權限,用sha-512加密啟動特定菜單項
可以在vim編輯器下使用:r!grub-md5-crypt
和r!grub-crypt
命令直接生成md5和sha-512加密密碼。啟動項編輯權限加密需要在選項信息前設置(第一個紅框),啟動特定菜單項需要在本啟動菜單項后面設置(第二個紅框)。
加密選項的語法為:
md5加密:password --md5 加密密碼
sha-512加密:password --encrypted 加密密碼
重啟后發現啟動界面沒有e編輯選項,提示鍵入p輸入密碼,證明已被加密
選擇加密過的啟動項,回車后彈出密碼輸入提示,證明已被加密
四、啟動過程錯誤修復
(一)僅保留/boot/grub目錄下的grub.conf文件
mv /boot/grub/* /app
mv /app/grub.conf /boot/grub
重啟后發現系統正常啟動,這說明進入stage 2必要的文件只有/boot/grub/grub.conf文件,其他文件只是stage1, stage 1_5, stage 2的備份文件
(二)grub的stage 1 丟失
mv /boot/grub/* /app
mv /app/grub.conf /boot/grub //在/boot/grub目錄中只保留grub.conf文件
dd if=/dev/zero of=/dev/sda bs=1 count=446 //刪除磁盤前446字節,即grub的stage 1
使用hexdump -C -n 512 /dev/sda
查看/dev/sda磁盤的前512字節,發現前446字節已經清零
重啟后,BIOS認為/dev/sda不是啟動磁盤,當沒有其他啟動介質時,啟動失敗停在黑屏中。光盤啟動,進入救援模式。在救援模式下,先進行切根操作,在使用grub-install /dev/sda
命令修復,成功后即可正常啟動。
修復成功后,可以看到在/boot/grub目錄下丟失的文件也恢復了
(三)grub的stage 1_5丟失
dd if=/dev/zero of=/dev/sda bs=1 count=10240 skip=512 seek=512 //除stage1之外的前20個扇區的內容全部清零
使用hexdump -C -n 10240 /dev/sda
查看/dev/sda磁盤的前10240字節,發現stage1_5確實已經清零。此時重啟系統,BIOS發現磁盤是引導磁盤開始stage1,但是stage1_5被破壞,故啟動失敗。光盤啟動,進入救援模式。
切根后,使用grub交互方式恢復stage1_5
grub> root (hd0,0)
grub> setup (hd0)
運行結果發現grub程序尋找/boot/grub下面的stage1_5文件嘗試恢復并成功,故這種修復方式需要確保/boot/grub/下的stage文件沒有缺損。修復成功后重啟成功。
(四)/boot/grub/grub.conf文件丟失
當刪除/boot/grub/grub.conf文件后,重新啟動系統進入stage 2但是因為沒有啟動項設置,進入提示符。此時,手動輸入關鍵啟動參數root, kernel, initrd等關鍵信息,boot回車重啟成功
(五)/boot/grub下的所有文件全部丟失
刪除/boot/grub目錄,此時stage2文件丟失,重新啟動系統報錯。進入救援模式,切根后使用grub-install /dev/sda
命令修復恢復stage2文件。此外,手動編寫grub.conf文件,提供啟動菜單,最基本的grub.conf文件如下:
default=0
timeout=6
title linux_2.6
kernel /vmlinuz-2.6.32-696.el6.x86_64 root=/dev/sda2
initrd /initramfs-2.6.32-696.el6.x86_64.img
重啟后,正常進入系統。
(六)/boot目錄下的所有文件丟失
/boot目錄下要恢復的文件如下:kernel文件,initramfs文件,grub stage2相關文件,grub.conf文件。這些文件的恢復操作上文都有所提及。
首先進入救援模式,切根(紅框1)之后,掛載光盤(紅框2),將光盤上的內核文件復制到/boot目錄下(紅框3),然后使用mkinitrd命令恢復initramfs文件(紅框4)
使用grub-install命令恢復stage2 相關文件
編輯grub.conf文件
重新啟動成功
(七)/sbin/init文件丟失
重啟后,會因為沒有/sbin/init文件而卡死在啟動過程中。此時重新啟動,編輯啟動項,改為用bash啟動。在bash環境下,用光盤重新安裝init程序對應的軟件包。
啟動項畫面鍵盤a鍵,進入啟動項命令行編輯頁面,指定由/bin/bash代替/sbin/init開始用戶空間的初始化操作,行尾添加init=/bin/bash
重啟后,發現可以在bash環境下操作。此時,用rpm命令查詢/sbin/init文件對應的安裝包為upstart,掛載光盤到/mnt目錄為安裝做準備。由于/目錄掛載狀態為只讀,重新掛載并設置為讀寫。
rpm重新安裝upstart軟件包。因為只是丟失了/sbin/init文件,所以需要添加--force
選項強制覆蓋安裝。
重新啟動后,成功進入系統。
(八)/etc/fstab文件和/boot目錄下的所有文件丟失
/boot目錄下的文件丟失的情況,在上文第6條已經說明。但是,由于/etc/fstab文件丟失,在救援模式下執行/etc/rc.d/rc.sysinit初始化時無法掛載分區,救援系統無法自動將根分區掛載至/mnt/sysimage下,使后續對/boot目錄文件丟失的修復操作無法進行。所以這種情況需要分兩步進行:第一步,重建/etc/fstab文件。第二步,重啟進入救援模式,再恢復/boot目錄內容。
第一次進入救援模式,提示找不到硬盤分區。
此時,手動重建/etc/fstab文件。通過fdisk -l /dev/sda
命令查看分區表,對每個分區表嘗試掛載,了解分區內容,找到/boot分區和根分區,并在重建/etc/fstab文件中設置掛載信息。(紅框1:確定未能成功掛載到/mnt/sysimage;紅框2:嘗試掛載/dev/sda1,掛載后分區沒有內容,結合fdisk命令提示本分區屬于啟動分區,確定此分區應為/boot分區;紅框3:嘗試掛載/dev/sda2,掛在后分區內容很明顯應為根分區。至于/dev/sda3,在fdisk命令結果已經顯示為swap分區,不用再嘗試掛載了)
此時重建fstab文件,需要注意由于之前根目錄掛載失敗,當前根分區掛載到/mnt/unknown目錄下,則命令應為vi /mnt/unknown/etc/fstab
。編輯時可以使用:r!blkid
讀入blkid的命令執行結果,加快編輯速度。保存退出,重啟進入救援系統,此時系統正確識別文件系統。
此時的錯誤環境與上文第6條錯誤相同,修復方法參照上文。本次只嘗試在安裝kernel和initramfs文件的過程中,使用rpm命令安裝光盤上的kernel的rpm包,提供另一種修復內核的方式。其他修復過程,完全相同。
此處需要注意的是:由于kernel的安裝文件只破壞了一部分,rpm安裝時必須添加--force選項強制覆蓋,否則會提示已經安裝而修復失敗。
(九)邏輯卷環境下/etc/fstab文件和/boot目錄下的所有文件丟失
與上文第8條錯誤相似,修復的方法也相似,但是需要考慮邏輯卷的特殊情況。重啟進入救援模式,首先使用blkid, fdisk等命令查看磁盤分區情況,/boot目錄不能被邏輯卷掛載,故/dev/sda1是boot分區,而/dev/sda2為邏輯卷。
lvscan命令發現當前的邏輯卷處于非活動狀態,要想掛載邏輯卷,需要激活邏輯卷組,執行vgchange -ay
激活所有邏輯卷,再用lvscan查看時發現已經處于活動狀態。由于邏輯卷的名稱非常直觀,省去了掛載邏輯卷查看內容判斷真實掛載分區的步驟。
此時應建立臨時掛載目錄如/mnt/temp
,掛載操作mount /dev/VolGroup/lv_root /mnt/temp
,隨后手動建立fstab文件于/mnt/temp/etc/目錄下。保存退出后,重啟再次進入救援模式。
此后的修復方式與第8條錯誤的修復方案相似,都是rpm強制重裝kernel的rpm包恢復/boot目錄下的kernel和initramfs文件,接下來是grub-install命令修復/boot/grub下的驅動文件,最后是手動重建/boot/grub/grub.conf文件。(紅框1:切換根目錄,紅框2:掛載光盤,紅框3:rpm重裝kernel包,紅框4:grub-install修復)
在手動建立grub.conf文件時,注意根目錄的名稱此時為邏輯卷,其他沒有變化。
保存重啟,系統正常啟動。