一、裁减说明及大体步骤

目标:裁减系统了解其工作原理,对linux系统运行的深入了解。让linux 仅仅只有bash 和几个简单的命令,并添加网卡模块实现联网功能。

1、分区格式化硬盘

2、将硬盘挂载到Linux主机上面,然后安装grub、复制内核文件、initrd文件、安装bash、网卡模块、init及建立一些系统运行必要的文件夹等

3、将做好的硬盘挂在另一台主机上面进行测试(注意:内核后面的参数)


二、准备

环境:

vmware 10.0 Linux version 2.6.32-358.el6.x86_64(内核版本)--CentOS 6.4的发行版


开始之前我先大概介绍一下系统的启运流程:

-->POST 加电自检,载入一小段内置的程序完成初始化及各硬件的检测

-->加载BIOS 并根据指定的引导次序引导(硬盘、网络、移动设备)

-->读取MBR中的BootLoader,(Grub)

-->根据grub 找到内核所在分区加载内核及initrd的微型文件系统

-->内核初始化之后去挂载真正的根

-->执行Init/etc/inittab/etc/rc.d/rc$RUNLEVEL


vmlinuz-2.6.32-358.el6.x86_64 --> linux 的内核文件

initramfs-2.6.32-358.el6.x86_64.img --> 同内核一块加载的一个临时的根文件系统,

用来支持两阶段的引导过程。initrd文件中包含了各种可执行程序和驱动程序,它们可以用来挂载实际的

根文件系统,然后再将这个initrd RAM磁盘卸载,并释放内存


三、安装过程

  1. 在现有系统上面加入一块新的硬盘,ls /dev/sd*,确定你新加的硬盘的label(我这里新加的硬盘是sdd,因为原来系统里面已经有三块硬盘了)


  1. 使用fdiskmke2fs对硬盘分区格式化,然后fdiks -l /dev/sdd 进行查看如下:

wKioL1Mb6tGQt4vOAAIKIj6mwiI848.jpg

注意:我这里把boot 单独分区,便于接下来演示grub 的安装,一般grub大小为200MB ,不要太小了。而其它分区你完全可以做成逻辑卷或者软raid 都是没有问题的。我的boot 所在分区是sdd1,sdd2为根分区,下文全部按照这样的格式


  1. 对这两个分区进行挂载使用

mkdir /mnt/{boot,sysroot}    //挂载前先在mnt目录下面创建两个目录作为boot ,root 的挂载点

mount -t ext4 /dev/sdd1 /mnt/boot

mount -t ext4 /dev/sdd2 /mnt/sysroot

这时时候可以mount  查看一下挂载情况

wKiom1Mb6wfiQGJkAAC19uLMQQo930.jpg

如上则显示挂载成功


  1. 接下来安装grub

grub-install --root-directory=/mnt/dev/sdd    //注意root-directory  参数,指得是grub 安装所在整个分区,也就是boot 所在挂载点(grub 安装会默认安装在具有$DIR/boot 的目录下面),如果改写成/mnt/boot,意思就是在在grub根分区里面建一个boot 并安装之,而grub根分区是boot ,就是在boot分区里面又建一boot并安装,这是不正确的。/dev/sdd 是设备命是要把grub的第一阶段放在哪块硬盘的MBR

wKiom1Mb6x2wpNB_AAF5SHTIutE982.jpg

然后拷贝内核、initrd 文件至boot分区里面

cp/boot/{vmlinuz-2.6.32-358.el6.x86_64,initramfs-2.6.32-358.el6.x86_64.img}/mnt/boot/

接下来编辑grub 配置文件

vim /mnt/boot/grub.conf

wKioL1Mb6wTBADjRAAFGLYghy-M330.jpg

default    //default后加一个数字n,表明是第 n+1个。需要注意的是,GRUB中,计数是从0开始的,default 0 表示默认的操作系统是这个第一个title 标注的系统


timeout    //timeout表示默认等待的时间,这儿是5秒钟。超过5秒,用户还没有作出选 择的话,系统将自动选择默认的操作系统


title   // 表示CentOS 的菜单项


root (hd0,0)    //指当前系统的第一块硬盘的一个分区,在grub中所有的硬盘标识都是hd,


kernel   //指明要grub引导要加载的内核文件,而“/”即是boot 也就是上面标记的(hd0,0),

ro readonly root 是要加载的真正的根文件系统后面跟路径/dev/sda2selinux=0 默认不开启,因为我们载减了root, 所以要重新指定 init=/bin/bash ,或者为我们自己写的一个脚本


initrd   // init RAM 磁盘文件所在位置


提示:如果你忘记了grub.conf 的文件内容格式,可以VIM 末行模式中输入 r /boot/grub/grub.conf 即把原系统中的grub.conf文件内容读入到当前文件中,进行修改


  1. 检查boot分区制作完毕之后,就可以去裁根分区了

载之前我们要在根分区里面创建一些系统运行的必要的文件夹

mkdir /mnt/sysroot/{bin,dev,etc,home,lib,lib64,proc,root,sbin,srv,sys,usr,var}

为了简单第一次就先把bash 移植到根分区上面,开机检测看能不能跑起来,移值bash 不仅仅只是移植二进制程序,重要的是二制程序运行所需要的一个动态库,可以用ldd `which bash` 查看。为了快速移植我这里写了一个shell 可以参考一下:

#!/bin/bash
#
shopt -s expand_aliases
DIRE='/mnt/sysroot'
exePath(){
        local comRoad=`which --skip-alias $1`
        local comPre=`dirname $comRoad`
#       echo "this is a test ${DIRE}${1}"
        if [[ -d ${DIRE}${comPre} ]];then
                cp $(which --skip-alias $1) ${DIRE}${comPre}
        else
                mkdir -p ${DIRE}${comPre}
                cp $(which --skip-alias $1) ${DIRE}${comPre}
        fi
}
libCp(){
                unalias $1 &> /dev/null
                local i=1
                alias ldd="ldd `which $1` | grep -o \"/[^[:space:]]\{1,\}.*o\.[^[:space:]]\{1,\}\""
                local linNum=`ldd | wc -l`
                                      
                while [[ $i -le $linNum ]];do
                        local nameLib=$(ldd | sed -n ${i}p)
                        local dirLib=$(dirname $nameLib)
                        if [[ -d ${DIRE}${dirLib} ]];then
                                cp $nameLib ${DIRE}${dirLib}
                        else
                                mkdir -p ${DIRE}${dirLib}
                                cp $nameLib ${DIRE}${dirLib}
                        fi
                        let i++
                done
}
while true;do
        read -p "Please input the COMMAND(no buitin):" comName
        if which $comName &> /dev/null ;then
                exePath $comName
                libCp $comName
        elif [[ "$comName" == "quit" ]] ;then
                exit 4
        fi
done

移植完之后关闭宿主机,新建一个虚拟机指定刚才的硬盘为新主机的硬盘开机测试。成功的话你会看到一个bash 命令行


  1. 这时候仅仅只能操作一些bash  功能,而我们要做的是实现微型主机开机自动上网功能。这里就面要为微系统里面安装网卡模块

lsmod   //查看当前系统已安装的模块

modinfo  MOD_NAME    //查看该模块的详细信息

找到网络模块e1000.ko所在位置并拷贝到/mnt/sysroot/lib64

为了实习查看、安装、检测等功能再移植一些必要的命令(利用上面提供的脚本)ifconfig,mount,lsmod,cd,ls,cp,cat,mv,rm,rmmod,insmod


开机时候为了系统安全性root 所在分区是只读挂载,而且为了实现微系统实现开机自动加载网络模块并且实现配置有网络属性,这里就需要自已定制init 实现其功能,grub.conf  中开机传递给内核的参数    init=/sbin/init

#!/bin/bash
#
mount-n -t proc proc /proc
mount-n -t sysfs sysfs /sys
mount-n -o remount,rw /dev/sda2 /
[[$? -eq 0 ]]&&echo "the / is success"
insmod/lib64/module/e1000.ko
ifconfigeth0 172.16.100.110/16
ifconfiglo 172.0.0.1/16
/bin/bash

把该脚本保存在/sbin/init ,别忘加上可执行权限


  1. 关闭宿主机,重新打开测试机ifconfig  查看网卡是否存在ip 地址。至此一个简单的系统就成功了。