Linux 操做系統啓動流程以及trouble shooting

最近在某個版塊看到有人討論GRUB的問題,這裏是我我的的一些理解。
我想大部分仍是正確的,但確定也有理解錯誤的地方,在這裏拋磚引玉了!

Linux系統啓動過程大體按照以下步驟進行(這是一個簡述):
第一階段:BIOS啓動引導階段;
                        在該過程當中實現硬件的初始化以及查找啓動介質;
                        從MBR中裝載啓動引導管理器(GRUB)並運行該啓動引導管理
第二階段:GRUB啓動引導階段;
                        裝載stage1
                        裝載stage1.5
                        裝載stage2
                        讀取/boot/grub.conf文件並顯示啓動菜單;
                        裝載所選的kernel和initrd文件到內存中
第三階段:內核階段:
                        運行內核啓動參數;
                        解壓initrd文件並掛載initd文件系統,裝載必須的驅動;
                        掛載根文件系統
第四階段:Sys V init初始化階段:
                        啓動/sbin/init程序;
                        運行rc.sysinit腳本,設置系統環境,啓動swap分區,檢查和掛載文件系統;
                        讀取/etc/inittab文件,運行在/et/rc.d/rc<#>.d中定義的不一樣運行級別的服務初始化腳本;
                        打開字符終端1-6號控制檯/打開圖形顯示管理的7號控制檯

同時在上述過程當中各階段所須要讀取的文件和操做的對象:
BIOS啓動引導階段                          GRUB啓動引導階段                    內核階段                            /init/sysinit階段
==================================================================================================
None                                         /boot/grub/grub.conf               /boot/vmlinuz-      /etc/rc.d/rc.sysinit
                                                /boot/grub/stage1_5               /boot/initrd-         /etc/inittab
                                                /boot/grub/stage2                                                         /etc/rc.d/rc<#>.d
                                                                                                                                 /etc/rc.d/init.d/*
                                                                                                                                              



(下面是詳細的過程)                                                                                                                      
第一階段:
系統上電開機後,主板BIOS(Basic Input / Output System)運行POST(Power on self test)代碼,檢測系統外圍關鍵設備(如:CPU、內存、顯卡、I/O、鍵盤鼠標等)。硬件配置信息及一些用戶配置參數存儲在主板的CMOS( Complementary Metal Oxide Semiconductor)上(通常64字節),實際上就是主板上一塊可讀寫的RAM芯片,由主板上的電池供電,系統掉電後,信息不會丟失。
執行POST代碼對系統外圍關鍵設備檢測經過後,系統啓動自舉程序,根據咱們在BIOS中設置的啓動順序搜索啓動驅動器(好比的硬盤、光驅、網絡服務器等)。選擇合適的啓動器,好比一般狀況下的硬盤設備,BIOS會讀取硬盤設備的第一個扇區(MBR,512字節),並執行其中的代碼。實際上這裏BIOS並不關心啓動設備第一個扇區中是什麼內容,它只是負責讀取該扇區內容、並執行,BIOS的任務就完成了。此後將系統啓動的控制權移交到MBR部分的代碼。
注: 在咱們的現行系統中,大多關鍵設備都是連在主板上的。所以主板BIOS提供了一個操做系統(軟件)和系統外圍關鍵設備(硬件)最底級別的接口,在這個階段,檢測系統外圍關鍵設備是否「準備好」,以供操做系統使用。

第二階段:
BIOS經過下面兩種方法之一來傳遞引導記錄:
第一,        將控制權傳遞給initial program loader(IPL),該程序安裝在磁盤主引導記錄(MBR)中
第二,        將控制權傳遞給initial program loader(IPL),該程序安裝在磁盤分區的啓動引導扇區中
不管上面的哪一種狀況中,IPL都是MBR的一部分並應該存儲於一個不大於446字節的磁盤空間中,由於MBR是一個不大於512字節的空間。
所以IPL僅僅是GRUB的第一個部分(stage1),他的做用就是定位和裝載GRUB的第二個部分(stage2);stage2對啓動系統起關鍵做用,該部分提供了GRUB啓動菜單和交互式的GRUB的shell。啓動菜單在啓動時候經過/boot/grub/grub.conf文件所定義的內容生成。在啓動菜單中選擇了kernel以後,GRUB會負責解壓和裝載kernel image而且將initrd裝載到內存中。最後GRUB初始化kernel啓動代碼。
完成以後後續的引導權被移交給kernel。

假設Boot Loader爲grub (grub-0.97),其引導系統的過程以下:
grub分爲stage1 (stage1_5) 和stage2兩個階段。stage1能夠當作是initial program loaderI(IPL),而stage2則實現了grub的主要功能,包括對特定文件系統的支持(如ext2,ext3,reiserfs等), grub本身的shell,以及內部程序(如:kernrl,initrd,root)等。
stage 1:MBR(512 字節,0頭0道1扇區),前446字節存放的是 stage1,後面存放硬盤分區表信息,BIOS將stag1載入內存中0x7c00處並跳轉執行。stage1(/stage1/start.S)的任務很是單純,僅僅是將硬盤0頭0道2扇區讀入內存。0頭0道2扇區內容是源代碼中的/stage2/start.S,編譯後512字節,它是stage2 或者stage1_5的入口。
注:此時stage1是沒有能力識別文件系統的,其定位硬盤0頭0道2扇區過程以下:
BIOS將stage1載入內存0x7c00處並執行,而後調用BIOS INIT13中斷,將硬盤0頭0道2扇區內容載入內存0x7000處,而後調用copy_buffer將其轉移到內存0x8000處。定位0頭0道2扇區有兩種尋址方式:LBA、CHS。
start.S的主要功能是將stage2或stage1_5從硬盤載入內存,若是是stage2,則載入0x820處;若是是 stage1_5,則載入0x2200處。
注:這裏的stage2或者stage1_5不是/boot分區/boot/grub目錄下的文件,這個時候grub尚未能力識別任何文件系統。分如下兩種狀況:
(1)假如start.S讀取的是stage1_5,它存放在硬盤0頭0道3扇區向後的位置,stage1_5做爲stage1和stage2中間的橋樑,stage1_5有識別文件系統的能力,此後grub纔有能力去訪問/boot分區/boot/grub目錄下的 stage2文件,將stage2載入內存並執行。
(2)假如start.S讀取的是stage2,一樣,這個stage2也不是/boot分區/boot/grub目錄下的stage2,這個時候 start.S讀取的是存放在/boot分區Boot Sector的stage2。這種狀況下就有一個限制:由於start.S經過BIOS中斷方式直接對硬盤尋址(而非經過訪問具體的文件系統),其尋址範圍有限,限制在8GB之內。所以這種狀況須要將/boot分區分在硬盤8GB尋址空間以前。
假如是情形(2),咱們將/boot/grub目錄下的內容清空,依然能成功啓動grub;假如是情形(1),將/boot/grub目錄下stage2刪除後,則系統啓動過程當中grub會啓動失敗。
這個地方常常要進行的操做:
是關於grub經常使用的幾個指令對應的函數:
grub>root (hd0,0)                                                                                                --root指令爲grub指定了一個根分區
grub>kernel /xen.gz-2.6.18-37.el5                                                                          --kernel指令將操做系統內核載入內存
grub>module /vmlinuz-2.6.18-37.el5xen ro root=/dev/sda2                                          --module指令加載指定的模塊
grub>module /initrd-2.6.18-37.el5xen.img                                                                 --指定initrd文件
grub>boot                                                                                                          --boot 指令調用相應的啓動函數啓動OS內核


第三階段:
如階段2所述,grub>boot指令後,系統啓動的控制權移交給kernel。Kernel會當即初始化系統中各設備並作相關配置工做,其中包括CPU、I/O、存儲設備等。
關於設備驅動加載,有兩部分:一部分設備驅動編入Linux Kernel中,Kernel會調用這部分驅動初始化相關設備,同時將日誌輸出到kernel message buffer,系統啓動後dmesg能夠查看到這部分輸出信息。另外有一部分設備驅動並無編入Kernel,而是做爲模塊形式放在initrd (ramdisk)中。
在2.6內核中,支持兩種格式的initrd,一種是2.4內核的文件系統鏡像image-initrd,一種是cpio格式。以 cpio 格式爲例,內核判斷initrd爲cpio的文件格式後,會將initrd中的內容釋放到rootfs中。
initrd是一種基於內存的文件系統,啓動過程當中,系統在訪問真正的根文件系統/時,會先訪問initrd文件系統。將initrd中的內容打開來看,會發現有bin、devetc、lib、procsys、sysroot、init等文件(包含目錄)。其中包含了一些設備的驅動模塊,好比scsi ata等設備驅動模塊,同時還有幾個基本的可執行程序 insmod, modprobe, lvm,nash。主要目的是加載一些存儲介質的驅動模塊,如上面所說的scsi ideusb等設備驅動模塊,初始化LVM,把/根文件系統以只讀方式掛載。
initrd中的內容釋放到rootfs中後,Kernel會執行其中的init文件,這裏的init是一個腳本,由nash解釋器執行。這個時候內核的控制權移交給init文件處理,咱們查看init文件的內容,主要也是加載各類存儲介質相關的設備驅動。
驅動加載後,會建立一個根設備,而後將根文件系統/以只讀的方式掛載。這步結束後釋放未使用內存並執行switchroot,轉換到真正的根/上面去,同時運行/sbin/init程序,開啓系統的1號進程,此後系統啓動的控制權移交給 init 進程。關於switchroot是在nash中定義的程序。
Linux Kernel須要適應多種不一樣的硬件架構,可是將全部的硬件驅動編入Kernel又是不實際的,並且Kernel也不可能每新出一種硬件結構,就將該硬件的設備驅動寫入內核。實際上Linux Kernel僅是包含了基本的硬件驅動,在系統安裝過程當中會檢測系統硬件信息,根據安裝信息和系統硬件信息將一部分設備驅動寫入 initrd 。這樣在之後啓動系統時,一部分設備驅動就放在initrd中來加載。

第四階段:
init進程起來後,系統啓動的控制權移交給init進程。
/sbin/init進程是全部進程的父進程,當init起來以後,它首先會讀取配置文件/etc/inittab,進行如下工做:
1)執行系統初始化腳本(/etc/rc.d/rc.sysinit),對系統進行基本的配置,以讀寫方式掛載根文件系統及其它文件系統,到此係統基本算運行起來了,後面須要進行運行級別的肯定及相應服務的啓動;
2)肯定啓動後進入的運行級別;
3) 執行/etc/rc.d/rc,該文件定義了服務啓動的順序是先K後S,而具體的每一個運行級別的服務狀態是放在/etc/rc.d/rcn.d(n=0~6)目錄下,全部的文件均連接至/etc/init.d下的相應文件。
4)有關key sequence的設置
5) 有關UPS的腳本定義
6)啓動虛擬終端/sbin/mingetty
7)在運行級別5上運行X
這時呈現給用戶的就是最終的登陸界面。
至此,系統啓動過程完畢:)
說明:
1)/etc/rc.d/rc.sysint -- System Initialization Tasks
它的主要工做有:
配置selinux,
系統時鐘,
內核參數(/etc/sysctl.conf),
hostname,
啓用swap分區,
根文件系統的檢查和二次掛載(讀寫),
激活RAID和LVM設備,
啓用磁盤quota
檢查並掛載其它文件系統
等等。

GRUB的基本原理以及對GRUB的操做控制方法:
GRUB全稱爲Grand Unified Boot Loader,是Linux操做系統主流的啓動引導管理器。主要做用是啓動和裝載Linux操做系統。系統啓動過程當中一旦完成了BIOS自檢,GRUB會被馬上裝載。在GRUB裏面包含了能夠載入操做系統的代碼以及將操做系統引導權傳遞給其餘啓動引導管理器的代碼。GRUB能夠容許用戶選擇使用不一樣的 kernel啓動系統,或者在啓動系統的過程當中設置不一樣的啓動參數。
而一般BIOS會如下面兩種方法之一來調用啓動引導管理器:
將控制權移交給於驅動器主引導記錄的initial program loader(IPL);
將控制權移交給其餘啓動引導管理器,再由他們將控制權移交給安裝在分區引導扇區的IPL
一般狀況下啓動引導管理器GRUB由兩部分組成(stage1和stage2):
stage1比較小,一般能夠駐留在MBR或者各個磁盤分區的啓動扇區中,主要做用是裝載stage2。
stage2比較大,從磁盤的啓動引導分區讀取
至於在stage1和stage2之間存在一個stage1.5,是由於starge1.5具備識別文件系統的能力。
在Linux系統中對GRUB的配置有兩種方法:
主要引導管理器:
會將啓動引導管理器的stage1安裝在MBR上,這時啓動引導管理器必須被配置爲能夠傳遞控制權到其餘操做系統;
次要引導管理器:
會將啓動引導管理器的stage1安裝在一些分區的引導扇區上,而其餘的啓動引導管理器會被安裝在MBR上,由他們來向Linux啓動引導管理器傳遞控制權。
GRUB在啓動過程當中能夠提供命令行交互界面,能夠從ext系列,reiserfs,fat等多種文件系統引導系統,而且能夠提供密碼加密功能,其內容在 /boot分區下,系統啓動過程當中由配置文件/boot/grub/grub.conf來定義啓動方式,對該配置文件的更改會當即生效。
在配置文件/boot/grub/grub.conf文件中定義的內容包括:
grub所在的分區,引導系統所使用的kernel文件位置,硬件初始化使用的initrd文件位置,以及啓動參數。
例如:
grub>root (hd0,0)                                                                                         --root指令爲grub指定了一個根分區
grub>kernel /xen.gz-2.6.18-37.el5                                                                   --kernel指令將操做系統內核載入內存
grub>module /vmlinuz-2.6.18-37.el5xen ro root=/dev/sda2                                   --module指令加載指定的模塊
grub>module /initrd-2.6.18-37.el5xen.img                                                          --指定initrd文件
grub>boot                                                                                                   --boot 指令調用相應的啓動函數啓動OS內核

可見其指定的內容大多數在/boot分區,若是切換到/boot分區以後會看到這些內容:
/boot/vmlinuz-*                 linux kernel的一個copy;
/boot/initrd*.img                初始化的ram disk文件
/boot/grub/device.map        linux設備名和grub設備名的映射文件
/boot/grub/grub.conf          主配置文件

一般GRUB出錯概率不是很大,但一旦出現問題恐怕採用最多的方式是重裝grub到MBR中。
在這種時候須要注意的問題有:
首先,設備映射關係:
GRUB裏面對設備名稱的定義和系統中對設備名稱的定義方法不同:
        (fd0)                /dev/fd0
        (hd0)                /dev/sda        /dev/hda
        (hd1)                /dev/sdb        /dev/hdb
如夠進入系統或者救援模式,可執行命令/sbin/grub-install /dev/sda(或者hda)進行GRUB重裝:
        # /sbin/grub-install device
處於某種緣由MBR中信息出錯可使用上面的命令將其重裝到磁盤主引導記錄中;可是若是在不能進入系統的狀況下就須要經過grub的命令行界面進行手動設置,這個時候就要注意上面所提到的映射關係。

同時,在grub命令行中對grub進行手動設置的時候須要注意所使用的命令:
        # root (hd0,0)                                --指定啓動分區
        # setup(hd0)                                  --表示將grub安裝在主引導記錄上
        # quit                                              --退出grub        shell

下面是一個完整的grub.conf文件內容:
[root@dhcp-0-195 ~]# cat /etc/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/VolGroup001/LogVol00
#          initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=30
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
password --md5 $1$apEcJWbA$DTJ8a6mKn/3yrTTSXBtdH0
title Red Hat Enterprise Linux Client (2.6.18-8.1.1.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-8.1.1.el5 ro root=/dev/VolGroup001/LogVol00 crashkernel=128M@16M
        initrd /initrd-2.6.18-8.1.1.el5.img

系統啓動運行級別的概念以及服務的定製方法;
當initrd能夠正常檢測和裝載以後,最後的工做就基本上由操做系統來進行了。當系統的init進程起來以後系統啓動的控制權移交給init進程。
/sbin/init進程是全部進程的父進程,當init起來以後,它首先會讀取配置文件/etc/inittab,進行如下工做:
1)執行系統初始化腳本(/etc/rc.d/rc.sysinit),對系統進行基本的配置,以讀寫方式掛載根文件系統及其它文件系統,後面須要進行運行級別的肯定及相應服務的啓動,(從這個角度能夠看出若是要定義系統的init動做,須要修改/etc/rc.d/rc.sysinit腳本)
2)經過對/etc/inittab文件的讀取肯定啓動後進入的運行級別;
3) 在相應的運行級別中執行/etc/rc.d/rcx.d目錄下的腳本名稱,該文件定義了服務啓動的順序是先K後S,而具體的每一個運行級別的服務狀態是放在 /etc/rc.d/rcn.d(n=0~6)目錄下,但這些文件均是到/etc/init.d下的相應文件的連接。
系統會按照在該目錄下的文件名稱和優先級執行對應運行級別目錄下的腳本:
在某個運行級別的對應目錄下,K開頭的服務被關閉,S開頭的服務被開啓,K在S開始以前執行,在執行過程當中按照數字來定義優先級,數字越低優先級越高。
4)按照/etc/rc.d/rcX.d目錄中的定義,系統會於後臺啓動相應的服務,若是要對某個運行級別中的服務進行更具體的定製,經過chkconfig命令來操做,或者經過setup/ntsys/system-config-services來進行定製。
5)在/etc/inittab文件中存在有關key sequence,UPS的腳本定義,啓動虛擬終端/sbin/mingetty的設置,這時呈現給用戶的就是最終的登陸界面。
也就是說後臺啓動的服務完畢以後,若是系統默認進入字符界面,則運行mgetty進入1-6號終端控制檯,若是系統默認進入圖形界面,則開啓gdm服務進入7號虛擬圖形控制檯。
至此,系統啓動過程完畢。

對於/etc/rc.d/rc.sysinit文件的說明:
/etc/rc.d/rc.sysint -- System Initialization Tasks 執行系統初始化任務的腳本。
它的主要工做有:
配置selinux,
系統時鐘,
內核參數(/etc/sysctl.conf),
hostname,
啓用swap分區,
根文件系統的檢查和二次掛載(讀寫),
激活RAID和LVM設備,
啓用磁盤quota
檢查並掛載其它文件系統

這是其基本要實現的工做內容:
#!/bin/bash
#
# /etc/rc.d/rc.sysinit - run once at boot time
#
# Taken in part from Miquel van Smoorenburg's bcheckrc.


# Check SELinux status
                
# Because of a chicken/egg problem, init_crypto must be run twice.  /var may be
# encrypted but /var/lib/random-seed is needed to initialize swap.

# Only read this once.

# Initialize hardware

# Set default affinity

# Load other user-defined modules

# Load modules (for backward compatibility with VARs)

# Start the graphical boot, if necessary; /usr may not be mounted yet, so we
# may have to do this again after mounting

# Configure kernel parameters

# Set the hostname.

# Initialize ACPI bits

# RAID setup

# Device mapper & related initialization

# Update quotas if necessary

# Remount the root filesystem read-write.

# Clean up SELinux labels

# Clear mtab

# Remove stale backups

# Enter mounted filesystems into /etc/mtab

# Mount all other filesystems (except for NFS and /proc, which is already
# mounted). Contrary to standard usage,
# filesystems are NOT unmounted in single user mode.

# Check to see if a full relabel is needed

# Start the graphical boot, if necessary and not done yet.

# Initialize pseudo-random number generator

# Use the hardware RNG to seed the entropy pool, if available

# Configure machine if necessary.

# Clean out /.

# Do we need (w|u)tmpx files? We don't set them up, but the sysadmin might...

# Clean up /var.  I'd use find, but /usr may not be mounted.

# Reset pam_console permissions

# Clean up utmp/wtmp

# Clean up various /tmp bits

# Make ICE directory

# Start up swapping.


如下是我在生產環境中所碰到的一些和GRUB修復有關的案例:
案例一:
GRUB沒法找到kernel image的問題:
產生這類型問題的緣由包括:
配置文件中指定了錯誤的kernel image名稱或者路徑,在/boot分區下kernel文件被刪除或者改名,kernel image文件被破壞,Raid-1磁盤陣列更換故障盤後信息不一樣步等。
對於這類型問題的解決方法:
能夠設法經過救援模式或者在開機的時候進入grub的shell,而後利用grub shell嘗試手動指定和裝載正確的kernel image信息或者在救援模式下檢查和重寫grub.conf文件。
須要注意的是,若是要經過救援模式進入grub命令行界面須要先chroot,即執行chroot /mnt/sysimage。在
grub>提示符以後執行:
# root (hd0,0)
# setup(hd0)
# quit
無論經過什麼樣的方法和配置,只要使GRUB可以正確找到kernel image是解決問題的關鍵。
在對grub修復的時候尤爲要注意MBR信息在軟件Raid上的恢復。
Linux的boot分區不能創建在軟件Raid-0上,可是能夠創建在Raid-1陣列上。也就意味着系統的GRUB也是同時寫入到Raid-1磁盤陣列兩塊盤的MBR中。可是若是這個信息一旦這個信息沒有正確寫入或者正常完成寫入,問題就會出現。
這種狀況多發於對Raid-1陣列中的壞盤進行更換的時候。
一個典型的例子是,用戶只有兩塊磁盤作Raid-1,他在兩塊盤上分別規劃了一樣的磁盤分區/boot swap以及/,對應的設備是md0,md1和md2。在其中的某一個磁盤出現問題的時候,用戶更換一塊新的磁盤,而且按照原來的盤規劃了/boot, swap以及/,同時使用了命令mdadm -A對三個md都進行了重組,重組可以順利完成,可是一旦重啓系統在出現一個GRUB的提示對話框以後引導中止。
從這個狀況看來,很顯然,md0,md1和md2內的數據都由原來的磁盤向新的磁盤進行了同步,可是MBR的內容和信息沒有同步過來。這就形成了系統啓動的失敗。
解決該問題的方法:
可使用救援模式引導系統,或者使得GRUB可以檢測到文件系統——即出現GRUB>提示符,執行下面的命令,將GRUB重裝到第一塊盤:
# root (hd0,0)
# setup(hd0)
# quit
而後執行,將GRUB重裝到第二塊盤:
# root (hd1,0)
# setup(hd0)
# quit
完成以後重啓系統。這種方法還能夠對付在BIOS中對啓動引導管理器進行的修改。

案例二:
None System or Disk Error和GRUB的關係:
某個用戶曾經報告一臺HP的DL380服務器上原有40G和140G兩塊硬盤,而且按照第一塊硬盤所可以提供的磁盤空間創建了一個軟件Raid-0磁盤陣列。該用戶在沒有拔除這兩塊硬盤的狀況下直接加入了兩塊新的硬盤並計劃對原有的Raid-0陣列進行擴容。但在插入硬盤重啓以後顯示「None System or Disk Error」,在用戶拔除這兩塊硬盤以後重啓還出現一樣的信息。
根據描述的系統啓動過程來看,這個none system or disk error的報錯,代表系統啓動引導過程當中並無裝在任何啓動引導管理器(GRUB)信息,而之因此沒有找到這些信息是由於這些磁盤的MBR裏面沒有用於引導的IPL或者說白了系統所用於引導的磁盤根本就不是啓動盤。看來系統並無使用用戶設想的磁盤做爲啓動引導磁盤。那麼也就時說這和在磁盤的GRUB沒有任何關係,咱們所要作的第一可以確保系統使用正確的磁盤引導,第二就是沒有對原有的GRUB進行任何錯誤的修改就行。
按照咱們對問題的分析,用戶更換了硬盤所在的槽位,問題獲得解決。
產生該問題的緣由是由於HP DL380服務器在安裝系統必須在陣列上進行,可是新加入的磁盤或者陣列會更改原來默認的啓動引導順序。儘管這和GRUB的修復沒有任何關係,可是可以準肯定位該問題的所在至少可以減小排錯的時間以及一些沒必要要的麻煩。

案例三:
在RHEL3中HP服務器上的cciss和system-map的問題:
衆所周知在GRUB中對設備進行命名的方法和系統命名的方法是不一樣的。無論系統中的啓動引導磁盤是sd接口仍是hd接口在GRUB中都會被統一識別爲 hd,而且hda/sdahd0,hdb/sdbhd1……依次類推。這和系統對設備的命名方式顯然存在一些差別,可是這種差別經過在 /boot/grub/device-map文件中進行解釋和映射來實現系統對兩種設備命名方法的映射。
這是一個device-map文件的內容:
遺憾的是,redhat老版本的操做系統如RHEL3的某個版本,在一些特殊的硬件上,如HP的cciss中對系統設備名和GRUB設備名的映射關係不正確而致使系統在這些硬件上沒法啓動。這能夠認爲是操做系統的一個bug,所幸該bug在RHEL3靠後的幾個發行版後都獲得了修復。
儘管碰到這種問題的概率極低,但須要明確一點,檢查設備映射是否正確也是GRUB排錯的一項內容。
這裏順別說一下:
cciss是惠普的smart array控制器的設備名,c0指channl 0,第一個SCSI通道,d0指邏輯盤1,d1指邏輯盤2……,p1指第一個分區,p2是第二個分區……。在這種狀況下,咱們能夠看到不少HP的服務器在經過該設備鏈接硬盤的時候,常常看到的設備是/dev/cciss/c0d0p1,/dev/cciss/c0d0p2, /dev/cciss/c0d0p3等。
案例四:
在GRUB中向kernel傳遞了錯誤的根分區信息致使系統kernel panic:
在GRUB的配置中,根分區信息的指定是必須的,可是一旦錯誤指定了根分區或者根分區文件文件系統或卷標被破壞都回致使在啓動引導過程當中出現kernel panic狀況。
這是在GRUB中對/分區指定的信息:
kernel /vmlinuz-2.6.18-8.1.1.el5 ro root=LABEL=/
那麼一旦/卷標被刪除,能夠經過e2label的方式從新建立,或者將其直接更改成:
kernel /vmlinuz-2.6.18-8.1.1.el5 ro root=/dev/sda2
即以直接指定/分區名的方式來指定根分區。
這個操做能夠在開機發現錯誤以後於GRUB命令行中直接修改,或者進入救援模式進行操做。當前所定義的內容若是成功,切記將其記錄到/etc/grub.conf或者/boot/grub/grub.conf文件中。
其實這是一個很是典型的錯誤,出錯的時候,屏幕上顯示的大概狀況以下:
Creating block devices
Creating root devices
mkrootdev:label / not found
Mounting root filesystem
Mount:error 2 mounting ext3
Pivotroot:pivot_root(/sysroot, /sysroot/initrd) failed:2
umount /initrd/proc failed:2
Freeing unused kernel memory:164k freed
Kernel panic:no init found.        Try passing init = option to kernel.
很顯然,這個時候若是是由於/文件系統沒法找到或者掛載成功,必須的內核模塊沒有加載成功或者initrd文件被破壞都有可能出現一樣的信息(這裏所指的模塊是包括了驅動器,硬件控制器以及做用於文件系統的驅動程序,固然若是是模塊形成系統啓動不成功的話,可使用mkinitrd命令對initrd文件進行重建)。
具體的命令是:
# mkinitrd –f /boot/initrd-.img
例如:
# mkinitrd –f /boot/initrd-2.6.9-42.ELsmp.img 2.6.9-24.ELsmp
在完成了initrd鏡像的重建以後能夠從新啓動系統。
若是問題確認是由於initrd鏡像被破壞而致使沒法識別文件系統,則經過上面的操做已經可以正確找到root文件系統並開啓init進程。

案例五:
該案例實際上和上面的案例有緊密關係。上面的案例中因爲GRUB沒法正確加載根文件系統而致使kernel panic。形成這個問題的緣由也是多種多樣。可是即使經過上面的修復可使得kernel加載根文件系統而且開啓init進程,那麼在下一步 rc.sysinit腳本執行過程當中任何區域出現錯誤也會致使系統沒法啓動。
由於在存儲方面,sc.sysinit腳本會初始化軟件raid以及lvm設備而後讀取/etc/fstab,因此這個時候若是/etc/fstab文件配置不正確,也會形成系統啓動不成功。
從出現的問題現象上基本能夠判定是/etc/fstab的問題,可是好在這個時候能夠進入修復模式,對問題的修復方法也容易不少。這是出現問題的時候的截屏:
Coundn’t find matching filesystem: LABEL=/
*** An error occurred during the file system check.
*** Dropping you to a shell; the system will reboot
*** when you leave the shell.
Give root password for maintenance
(or type Control-D to countinus):
在這個界面中輸入root密碼能夠在出現的修復模式中運行命令修復。
另一個會形成該現象的緣由是在讀/etc/fstab文件並掛載文件系統的時候文件系統檢測失敗。在這種狀況下須要確保文件系統處於umount狀態下運行e2fsck。

案例六:
對initrd文件的修復:
initrd是一種基於內存的文件系統,啓動過程當中,系統在訪問真正的根文件系統/時,會先訪問initrd文件系統。將initrd中的內容打開來看,會發現有bin、devetc、lib、procsys、sysroot、init等文件(包含目錄)。其中包含了一些設備的驅動模塊,好比scsi ata等設備驅動模塊,同時還有幾個基本的可執行程序 insmod, modprobe, lvm,nash。主要目的是加載一些存儲介質的驅動模塊,如上面所說的scsi ideusb等設備驅動模塊,初始化LVM,把/根文件系統以只讀方式掛載。
Linux Kernel須要適應多種不一樣的硬件架構,可是將全部的硬件驅動編入Kernel又是不實際的,並且Kernel也不可能每新出一種硬件結構,就將該硬件的設備驅動寫入內核。實際上Linux Kernel僅是包含了基本的硬件驅動,在系統安裝過程當中會檢測系統硬件信息,根據安裝信息和系統硬件信息將一部分設備驅動寫入 initrd 。這樣在之後啓動系統時,一部分設備驅動就放在initrd中來加載。
因此在啓動過程當中initrd文件會在1號進程被開啓以前執行,若是一旦initrd文件被破壞或者非正常的更改就會致使系統沒法啓動。根據之前對 initrd原理的解釋,initrd中的init是使用nash解釋器去執行,因此係統啓動沒有到nash的時候停住,能夠基本上判斷是initrd這裏hang住。比較可行的辦法是經過mkinitrd命令重建initrd,生成一個新的用於初始化和裝載模塊的ramdisk鏡像。
具體的命令是:
# mkinitrd –f /boot/initrd-.img
例如:
# mkinitrd –f /boot/initrd-2.6.9-42.ELsmp.img 2.6.9-24.ELsmp
或者經過強制的方式重裝一個kernel,由於kernel基本上以不變的方式覆蓋原來kernel所安裝的內容,同時會在rpm安裝kernel命令中有重建initrd的腳本:
[root@dhcp-0-195 ~]# rpm -q --scripts kernel
postinstall scriptlet (using /bin/sh):
if [ `uname -i` == "x86_64" -o `uname -i` == "i386" ]; then
  if [ -f /etc/sysconfig/kernel ]; then
    /bin/sed -i -e 's/^DEFAULTKERNEL=kernel-smp$/DEFAULTKERNEL=kernel/' /etc/sysconfig/kernel || exit $?
  fi
fi
/sbin/new-kernel-pkg --package kernel --mkinitrd --depmod --install 2.6.18-8.1.1.el5 || exit $?
if [ -x /sbin/weak-modules ]
then
    /sbin/weak-modules --add-kernel 2.6.18-8.1.1.el5 || exit $?
fi
preuninstall scriptlet (using /bin/sh):
/sbin/new-kernel-pkg --rminitrd --rmmoddep --remove 2.6.18-8.1.1.el5 || exit $?
if [ -x /sbin/weak-modules ]
then
    /sbin/weak-modules --remove-kernel 2.6.18-8.1.1.el5 || exit $?
fi

案例七:
在系統啓動過程當中對rc.sysinit腳本進行定位的方法:
在最近對一些客戶問題進行處理的時候有時會發現一些由於對/etc/rc.d/rc.sysinit腳本的更改而致使系統沒法啓動成功的問題。因爲 rc.sysinit腳本所負責系統環境變量、存儲,設備初始化、配額等多個部分的設置和初始化,因此在啓動過程當中出現若是是由於rc.sysinit的更改而出現dead lock不容易定位是哪一個地方的設置出現問題。
因爲rc.sysinit腳本是由多個部分組成,一個比較簡單的辦法就是在每一個部分之間加上一個標記。例如:
sleep 10
echo 「sleep 10」
這樣系統在執行rc.sysinit腳本過程當中的每一個部分都會停10秒並顯示一個提示信息「sleep 10」,這樣能夠經過顯示的信息定位大概問題出在哪裏。

案例八:
在系統啓動過程當中出現的初始化和啓動swap的時候系統出現的dead lock的解決方法:
在某些狀況下系統啓動到enable swap的時候會長時間的dead lock現象,在某些時候系統懸掛於此而始終不能打開mgetty終端提供控制檯。
swap交換分區是一個特殊的文件系統,該文件系統的基本做用就是可使操做系統將一部分駐留於內存而暫時不操做的進程轉移到swap分區中而騰出物理內存給新的須要執行的進程。
紅帽官方推薦的使用交換分區的比例是2G物理內存如下,交換分區爲物理內存的1.5-2倍;4G以上物理內存推薦交換分區與物理內存爲1:1。
但通常狀況下可能會有多種緣由形成swap文件系統的初始化失敗並且因爲swap分區內容在用戶空間沒法操做,因此很難準確得到緣由。但不少時候系統在啓動到swap的時候並無真正的dead lock,而是因爲以後的一些其餘服務的啓動影響了系統打開終端並給用戶形成系統啓動swap失敗的假象。
基本上一些啓動順序在swap以後的服務都有可能產生這種影響,但因爲系統在安裝以後默認加載在kernel parameter 「rhgb quite」會掩蓋整個的啓動過程,因此在系統啓動到GRUB的時候經過進入GRUB菜單,手動刪除「rhgb quite」會防止在啓動的時候屏蔽啓動過程並顯示完整的啓動信息。
另外這個rhgb(redhat graphical boot)自己就有可能干擾後續的服務啓動。在不少時候實際上後面的服務已經起來,可是系統會顯示enable swap並停在該處。在這個時候可使用ping的方法或者ssh去探測該主機是否已經能夠登陸並提供服務。linux

相關文章
相關標籤/搜索