1、linux系统启动流程:

    post--->根据主板上ROM固件中的系统设置、判断从哪个设备启动--->读取设备的第一扇区的前512字节(MBR),判断用什么bootloader引导系统到内存中--->启动内核程序,有可能会借助于ramdisk--->将内核装载在内存中,建立临时根文件系统(rootfs),完成根系统切换--->启动第一个用户进程init(pid1:/sbin/init、/etc/inittab:设定默认运行级别、etc/init/*.conf:init的配置文件、初始化脚本参数及启动对应级别下的服务)--->启动终端


2、GRUB(bootloader):grand unified bootloader

    grub0.x:grub legacy(centos5/6)

    grub1.x:grub2


3、grub legacy:此版本的grub分为三个阶段

    stage1:引导安装在MBR中的引导程序(bootloader)

    stage1_5:MBR之后的扇区,让stage1中的bootloader能识别stage2所在分区上的文件系统

    stage2:存放在磁盘上的grub(存放位置:/boot/grub),grub的配置文件:/boot/grub/grub.conf,在etc目录下有此文件的连接文件:/etc/grub.conf,如下:

            [root@localhost ~]# ll /etc/grub.conf 

            lrwxrwxrwx. 1 root root 22 Dec 31 20:14 /etc/grub.conf -> ../boot/grub/grub.conf

            [root@localhost ~]# 

    注意:stage2阶段及内核通常放置于同一个磁盘分区。

grub.conf的配置示例:

[root@localhost boot]# cat grub/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/mapper/VolGroup-lv_root

#          initrd /initrd-[generic-]version.img

#boot=/dev/sda

default=0

timeout=5

splashimage=(hd0,0)/grub/splash.xpm.gz

hiddenmenu

title Red Hat Enterprise Linux (2.6.32-358.el6.x86_64)

root (hd0,0)

kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS.UTF-8 rd_NO_MD rd_LVM_LV=VolGroup/lv_swap SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=VolGroup/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet

initrd /initramfs-2.6.32-358.el6.x86_64.img

[root@localhost boot]# 


4、stage2 grub的作用:

    ①、提供菜单,并提供交互命令接口

        e:编辑模式,用于编辑菜单

        c:命令模式,交互式接口

    ②、加载用户选择的内核或操作系统

        允许传递参数给内核

        可隐藏此菜单

    ③、为grub菜单提供了保护机制

        为编辑菜单进行认证

        为启动内核或操作系统进行认证


5、grub根介绍:

grub一般放在的目录下/boot/grub,那么/boot这个目录是否单独分区就直接决定了grub所在根(/)的位置,

如果一块磁盘上分了两个区a和b,分区a单独给boot用(即存在grub、vmlinuz),分区b单独给根(/)用,那么/boot/grub的根就是磁盘分区a,此时grub的根即为分区a;

如果一块磁盘上就分了一块区,并将grub、vmlinuz放置于/boot下,那么此时grub的根为/boot,


boot被做成单独的简单分区,而根(/)被放在逻辑卷中,即boot可以不使用逻辑卷,可以是单独分区,centos5/6默认是将根(/)放在逻辑分区上的。

注意:grub不能访问软raid、逻辑卷等复杂操作。


6、grub识别设备的方法实现:

 (hd#,N)

    hd:hardware disk,硬盘

    #:第#块磁盘,用数字表示,从0开始编号

    N:硬盘的第N个分区,用数字表示,从0开始编号

如:(hd0,0):表示第一块磁盘的第一个分区,注意“()”括号必须写,固定格式。


7、grub的命令行接口

    help:获取命令列表

    help KEYWORD:获取特定命令的使用帮助

    find:搜索磁盘上的文件;格式:find(hd#,N)/PATH/TOSOMEFILE

        如:find(hd0,0)/vmlinuz-2.6.32-504.el6.x86_64

    root (hd#,N):设定(hd#,N)为grub的根,即设置哪块磁盘哪个分区为根,此时可以用find直接去查找文件,如:find /vmlinuz-2.6.32-504.el6.x86_64

    kernel /PATH/TO/SOMEFILE:设定本次启动时用到的内核文件在哪里,内核文件通常命名为linuz,z表示压缩;

        kernel除了指定内核文件位置之外,还可以添加许多内核支持使用的命令参数,如:init=/bin/init,selinux=0等等

    initrd /PATH/TO/SOMEFILE:用来指ramdisk文件在哪里,即设定为选定的内核提供额外文件的ramdisk,需要注意的是:ramdisk的版本号与内核的版本号必须完全匹配

    boot:引导启动选定的内核


grub.conf的配置示例:

[root@localhost boot]# cat grub/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/mapper/VolGroup-lv_root

#          initrd /initrd-[generic-]version.img

#boot=/dev/sda

default=0    //启动的默认菜单项,即title的编号,默认从0开始编号,0、1、2、3....

timeout=5    //菜单项默认显示时间

splashimage=(hd0,0)/grub/splash.xpm.gz  //grub菜单的背景图片,640*480的14位图

hiddenmenu  //隐藏菜单

password [--md5] 12345678   //定义编辑菜单的密码认证,--MD5可选,不过不用md5加密直接写明文密码即可

title Red Hat Enterprise Linux (2.6.32-358.el6.x86_64)    //定义菜单项,即开机显示的菜单选项

root (hd0,0)   //设定grub根所在位置

kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS.UTF-8 rd_NO_MD rd_LVM_LV=VolGroup/lv_swap SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=VolGroup/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet   ///vmlinuz-2.6.32-358.el6.x86_64设定启动的内核文件,root=/dev/mapper/VolGroup-lv_root设定真正的根文件系统位置(设备文件的位置)

initrd /initramfs-2.6.32-358.el6.x86_64.img    //设定与内核匹配的ramdisk文件

password [--md5] 12345678     //启动选定内核或操作系统是的密码认证

[root@localhost boot]# 


注意:可以用grub-md5-crypt命令生成密码密码

示例:

[root@localhost ~]# grub-md5-crypt 

Password: 

Retype password: 

$1$YQoXf/$JhHIskqgm8tlc7YdIQJnx.

[root@localhost ~]# 



8、进入单用户模式:

     ①、编辑grub菜单(选定要编辑的title,然后使用“e”命令)

     ②、在选定的kernel后附加:数字1或s或S或single,这几个参数都可以实现进入单用户模式。

    ③、在kernel所在行键入“b”键,进入单用户


grub配置文件丢了,会显示grub提示符,此时只需要启动系统,然后编辑一个grub

如果grub文件坏了,如grub stage1坏了,只要bootloader坏了,磁盘上所有系统都将无法引导,此时只能修复bootloader(如:重新安装grub),如进入救援模式或把硬盘拆下来放到其他系统上使用grub-install命令重新安装grub文件。

重新安装grub的命令:grub-install


9、grub-install:重新安装grub(这是一个完整安装,会安装三个不同阶段的文件)

场景一:主机有两块硬盘,想给第二块磁盘安装grub

场景二:主机上没有grub,但是可以启动(可以借助光盘上的grub引导系统,开始时只要有grub菜单或者能进入grub提示符,就可以指定grub根文件在光盘上、内核文件在光盘上,内核文件在哪没有关系;可以从光盘、u盘启动系统)

场景三:windows和linux双系统共存,建议先安装windows再安装linux,因为windows的引导文件不能引导linux,如果先安装linux再安装windows的话,那么windows的bootloader会覆盖掉linux的


安装示例步骤:

①、在系统上安装一块新的硬盘

    [root@localhost ~]# fdisk -l /dev/[sh]d[a-z]

    Disk /dev/sda: 10.7 GB, 10737418240 bytes

    255 heads, 63 sectors/track, 1305 cylinders

    Units = cylinders of 16065 * 512 = 8225280 bytes

    Sector size (logical/physical): 512 bytes / 512 bytes

    I/O size (minimum/optimal): 512 bytes / 512 bytes

    Disk identifier: 0x0005cab3


       Device Boot      Start         End      Blocks   Id  System

    /dev/sda1   *           1          64      512000   83  Linux

    Partition 1 does not end on cylinder boundary.

    /dev/sda2              64        1306     9972736   8e  Linux LVM


    Disk /dev/sdb: 2147 MB, 2147483648 bytes       //sdb上没有分区,需要先创建一个分区用来作为boot分区,如步骤②

    255 heads, 63 sectors/track, 261 cylinders

    Units = cylinders of 16065 * 512 = 8225280 bytes

    Sector size (logical/physical): 512 bytes / 512 bytes

    I/O size (minimum/optimal): 512 bytes / 512 bytes

    Disk identifier: 0x00000000

    [root@localhost ~]# 

②、创建分区:

    #fdisk /dev/sdb   //可以创建多个分区,用p命令显示如下    

      Device Boot      Start         End      Blocks   Id  System

    /dev/sdb1               1         100      802226   83  Linux

    /dev/sdb2             101         126      208845   82  Linux swap / Solaris

    /dev/sdb3             127         261     1084387+  83  Linux

    [root@localhost ~]# partx  -a /dev/sdb    //重新识别分区

    [root@localhost ~]# cat /proc/partitions    //查看分区信息   

    major minor  #blocks  name

       8        0   10485760 sda

       8        1     512000 sda1

       8        2    9972736 sda2

       8       16    2097152 sdb

       8       17     802226 sdb1

       8       18     208845 sdb2

       8       19    1084387 sdb3

     253        0    7938048 dm-0

     253        1    2031616 dm-1

    [root@localhost ~]# 

    [root@localhost ~]# mke2fs -t ext4 /dev/sdb1   //格式化分区为ext4类型的文件系统

    [root@localhost ~]# mke2fs -t ext4 /dev/sdb3   

    [root@localhost ~]# mkswap /dev/sdb2   

③、创建boot目录,并将sdb1挂载到root目录:grub比较较真,需要认到boot目录,在其下放置grub文件。

    [root@localhost ~]# mkdir /mnt/boot

    [root@localhost ~]# mount /dev/sdb1  /mnt/boot/

    [root@localhost ~]# ls /mnt/boot/

    lost+found

    [root@localhost ~]# 

    [root@localhost ~]# grub-install --root-directory=/mnt /dev/sdb    //将grub安装到磁盘sdb上,由于sdb1要成为grub的根,因此--root-directory=/mnt设置grub的根为mnt,注意,不要写成/mnt/boot,因为grub会自己找boot目录

    Probing devices to guess BIOS drives. This may take a long time.

    Installation finished. No error reported.

    This is the contents of the device map /mnt/boot/grub/device.map.

    Check if this is correct or not. If any of the lines is incorrect,

    fix it and re-run the script `grub-install'.

    (fd0)/dev/fd0

    (hd0)/dev/sda

    (hd1)/dev/sdb

    [root@localhost ~]# 

    [root@localhost ~]# ls /mnt/boot/   //验证grub会自动找boot并在其下有个grub目录

    grub  lost+found

    [root@localhost ~]# 

    [root@localhost ~]# ls /mnt/boot/grub/

    device.map     ffs_stage1_5      minix_stage1_5     stage2           xfs_stage1_5

    e2fs_stage1_5  iso9660_stage1_5  reiserfs_stage1_5  ufs2_stage1_5

    fat_stage1_5   jfs_stage1_5      stage1             vstafs_stage1_5    //stage1已经安装在sdb1这块磁盘上了

            //注意此处没有grub配置文件,grub配置文件只能自己写。写这个文件需要有内核文件和initrd文件,由于此处没有,只能去拷贝放在此目录下

    [root@localhost ~]# 

    [root@localhost ~]# cp /boot/vmlinuz-2.6.32-358.el6.x86_64  /mnt/boot/        //为了生成grub配置文件必须要有的

    [root@localhost ~]# cp /boot/initramfs-2.6.32-358.el6.x86_64.img  /mnt/boot/   //为了生成grub配置文件必须要有的

    [root@localhost ~]# vi /mnt/boot/grub.conf   //编辑一个grub配置文件

    default=0

    timeout=5

    title centos6 (custom)

    root (hd0,0)      

    kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/sda3 init=/bin/bash    //第一个init程序不再是/sbin/init程序 而是/bin/bash作为第一个应用程序

    initrd /initramfs-2.6.32-358.el6.x86_64.img

    [root@localhost ~]#

    [root@localhost ~]# mkdir /mnt/sysroot //创建一个临时根文件目录名

    [root@localhost ~]# mount /dev/sdb3 /mnt/sysroot/   //sdb3作为临时根         

    [root@localhost ~]# cd /mnt/sysroot/    

    [root@localhost sysroot]# mkdir -pv etc bin lib sbin lib64 dev proc sys tmp var usr var home root mnt media    //创建根下应有的目录

    

    [root@localhost sysroot]# cp /bin/bash /mnt/sysroot/bin/    //复制一个bash,做为系统启动后的测试用

    [root@localhost sysroot]# ldd /bin/bash   //查看程序所依赖的库文件有哪些

linux-vdso.so.1 =>  (0x00007fff7188d000)   //库文件访问入口

libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007ff09692f000)

libdl.so.2 => /lib64/libdl.so.2 (0x00007ff09672b000)

libc.so.6 => /lib64/libc.so.6 (0x00007ff096397000)

/lib64/ld-linux-x86-64.so.2 (0x00007ff096b55000)

    [root@localhost sysroot]# cp /lib64/libtinfo.so.5 /mnt/sysroot/lib64/   //复制库文件到相应的目录下,模仿此块硬盘启动的bash程序

    [root@localhost sysroot]# cp /lib64/libdl.so.2  /mnt/sysroot/lib64/

    [root@localhost sysroot]# cp /lib64/libc.so.6 /mnt/sysroot/lib64/

    [root@localhost sysroot]# cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/

    [root@localhost sysroot]# 

    [root@localhost sysroot]# chroot /mnt/sysroot/    //测试临时根文件系统是否可用

    bash-4.1#     //由于只复制了一个bash程序,所以此处显示如此

    bash-4.1# ls   //由于只复制了一个bash程序,所以此处显示如此 

    bash: ls: command not found

    bash-4.1# exit    //bash内置命令

    exit

    [root@localhost sysroot]# 

    [root@localhost boot]# sync  //同步到磁盘

至此,配置完成。

验证:将第二块磁盘放在到一个新系统中,做为唯一一块盘看看是否可行 selinux=0



10、安装本机grub(grub坏掉了,但是没有重启)(注意:bootloader在grub的第一阶段,grub的第一阶段放置于mbr上,如果grub第一阶段文件坏了,就看到不到引导菜单)

方法一:如果有备份:

    [root@localhost ~]# dd if=/dev/sda of=/root/mbr.bak count=1 bs=512    //备份mbr

    [root@localhost ~]# dd if=/dev/zero of=/dev/sda bs=200 count=1    //破坏mbr,将前200字节用“0”来填充

    [root@localhost ~]# grub-install --root-directory=/dev/sda    //安装grub修复。

修复完成,可以重启验证

注意:此方法不要求grub下有必要的文件(stage1、stage1_5、stage2)



方法二:

[root@centos6 ~]# grub

Probing devices to guess BIOS drives. This may take a long time.



    GNU GRUB  version 0.97  (640K lower / 3072K upper memory)


 [ Minimal BASH-like line editing is supported.  For the first word, TAB

   lists possible command completions.  Anywhere else TAB lists the possible

   completions of a device/filename.]

grub> root (hd0,0)    //指定grub所在的根目录

root (hd0,0)

 Filesystem type is ext2fs, partition type 0x83

grub> setup (hd0)     //安装grub的第一阶段至hd0中;setup用来安装grub的第一阶段,hd0用来指定硬盘

setup (hd0)

 Checking if "/boot/grub/stage1" exists... no

 Checking if "/grub/stage1" exists... yes

 Checking if "/grub/stage2" exists... yes

 Checking if "/grub/e2fs_stage1_5" exists... yes

 Running "embed /grub/e2fs_stage1_5 (hd0)"...  27 sectors are embedded.

succeeded

 Running "install /grub/stage1 (hd0) (hd0)1+27 p (hd0,0)/grub/stage2 /grub/grub.conf"... succeeded

Done.

grub> quit

quit

[root@centos6 ~]# 

修复完成,可以重启验证



    

        

11、紧急救援模式下修复grub

当grub文件被破坏(如mbr中的前446字节坏掉,此时又重新启动了),则现在应该进行紧急救援修复,步骤如下:

    ①、插入安装镜像光盘

    ②、重启电脑,选择从光盘引导;菜单项选择“rescue install system”(紧急救援模式,此种模式类似windows的WPE),或者敲入esc键,在命令提示符下输入:linux rescue 

    ③、进入shell后,改变系统根目录至临时根(#chroot /mnt/sysimage),这一步很重要

    ④、#grub-install --root-directory=/ /dev/sda     //安装grub至磁盘sda上,并将根目录设置为“/”它会自动去找/boot。