一、定制属于自己的内核

    1、在原有CentOS5.9中添加一块IDE硬盘,分2个磁盘并格式化为ext3文件系统

    2、挂载分区

        mkdir /mnt/boot

mkdir /mnt/sysroot

mount /dev/hda1 /mnt/boot

moutn /dev/hda2 /mnt/sysroot

    3、复制系统内核到/mnt/boot下:cp /boot/vmlinuz-2.6.18-348.el5 /mnt/boot/vmlinuz

    4、解压展开initrd文件:

mkdir test

cd test

zcat /boot/initrd-2.6.18-348.el5.img | cpio -id

    5、编辑init文件vim init:(修改其中一行为mkrootdev -t ext3 -o defaults,ro /dev/hda2;注释掉#resume LABEL=SWAP-sda5;.,+20s@^@#@g;)

***lib下没用的dm开头的文件:

cd lib/

rm -f dm-*

    6、切换到test目录制作新的initrd文件:

cd ..

find . | cpio -H newc --quiet -o | gzip -9 > /mnt/boot/initrd.gz(按照原有文件格式归档)

ls -lh /mnt/boot(可查看initrd文件大小)

    7、创建grub:

grub-install --root-directory=/mnt /dev/hda

ls /mnt/boot

    8、编辑grub文件

vim /mnt/boot/grub/grub.conf

default=0

timeout=3

title Magedu Linux(2.6.18)

root (hd0,0)

kernel /vmlinuz

initrd /initrd.gz

    9、创建核心的根文件系统(不能单独分区的):

cd /mnt/sysroot

mkdir etc/rc.d/init.d bin sbin proc sys dev lib root mnt media var/{log,run,lock/subsys,tmp} usr/{bin,sbin,local} tmp home opt boot -pv

    10、创建系统初始化的inittab配置文件:

        vim /mnt/sysroot/etc/inittab

id:3:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit

    11、创建rc.sysinit文件

vim /mnt/sysroot/etc/rc.d/rc.sysinit

#!/bin/bash

#

echo -e "\tWelcome to \033[34mMageEdu Team\033[0m Linux."

/bin/bash

添加可执行脚本权限:chmod +x etc/rc.d/rc.sysinit

    12、用脚本移植核心的可执行程序:

vim binary.sh

#!/bin/bash

#

DEST=/mnt/sysroot

libcp() {

  LIBPATH=${1%/*}

  [ ! -d $DEST$LIBPATH ] && mkdir -p $DEST$LIBPATH

  [ ! -e $DEST${1} ] && cp $1 $DEST$LIBPATH && echo "copy lib $1 finished."

}


bincp() {

  CMDPATH=${1%/*}

  [ ! -d $DEST$CMDPATH ] && mkdir -p $DEST$CMDPATH

  [ ! -e $DEST${1} ] && cp $1 $DEST$CMDPATH


  for LIB in  `ldd $1 | grep -o "/.*lib\(64\)\{0,1\}/[^[:space:]]\{1,\}"`; do

    libcp $LIB

  done

}


read -p "Your command: " CMD

until [ $CMD == 'q' ]; do

   ! which $CMD && echo "Wrong command" && read -p "Input again:" CMD && continue

  COMMAND=` which $CMD | grep -v "^alias" | grep -o "[^[:space:]]\{1,\}"`

  bincp $COMMAND

  echo "copy $COMMAND finished."

  read -p "Continue: " CMD

done

添加脚本执行权限:chmod +x binary.sh

执行脚本,移植如下命令:./binary.sh

init,bash,ls, touch,mkdir,rm,mv,cp ,cat,mount,umount,vi,vim,chmod,chown,ping,ifconfig,insmod,modprobe,rmmod,route,halt,reboot,shutdown,hostname

    13、切换目录测试:chroot /mnt/sysroot/

    14、同步数据到磁盘:sync 

    15、新建主机(内存为256即可)挂载第二块硬盘,启动测试效果(测试结果应该是能够正常启动,但仅能查看文件系统)。

二、系统启动流程回顾

    1、系统启动流程:

        POST(检测硬件)-->BIOS(Boot Sequence按照设备的引导次序找MBR)-->BootLoader(MBR)-->Kernel(RHEL5:initrd,RHEL6:initramfs)-->init(/etc/inittab)

    RHEL6的init程序:

        upstart项目的init程序:

            /etc/inittab

            /etc/init/*.conf

    2、内核(Kernel)初始化完成的工作:

        硬件探测

        装载驱动

        挂载根文件系统(rootfs)

        启动用户空间中的第一个进程init

        initrd文件是内核和根文件系统的中间层,起到连接作用。

    3、/etc/inittab(init)完成的工作: 

        设定默认运行级别

        系统初始化(依赖脚本/etc/rc.d/rc.sysinit进行)

        运行指定级别的服务脚本:/etc/rc.d/init.d/

        /etc/rc.d/rc#.d/下的链接文件链接的是init.d下的文件

            rc0.d--rc6.d

                K*

                S*

            00-99:运行次序,数字越小越先执行

        启动虚拟终端

        启动图形终端

    4、/etc/rc.d/rc.sysinit系统初始化:

        检测并以读写方式重新挂载根文件系统;

        设定主机名;

        检测并挂载/etc/fstab中的其它文件系统;

        启动swap分区;

        初始化外围硬件设备的驱动;

        根据/etc/sysctl.conf设定内核参数;

        激活udev和selinux;

        激活LVM和RAID设备;

        清理过期锁和PID文件;

        装载键映射(键盘功能);

    5、mount命令

        -n: 挂载时不更新/etc/mtab文件;

        cat /proc/mounts可查看当前挂载的所有设备

三、定制属于自己的内核(接一步骤)


如何解决新主机只读问题:

    1、在新的主机上挂载根目录:mount -n -o remount,rw /

        可创建文件touch /tmp/a.txt

        可测试结果……


如何实现新主机重启和关机:

    2、编辑脚本实现新主机关机前要做的任务:

        cd /mnt/sysroot

        vim etc/rc.d/rc.sysdone

#!/bin/bash

#

sync

sleep 1

sync

exec /sbin/halt -p

        添加脚本执行权限:chmod +x etc/rc.d/rc.sysdone

        执行移植脚本,移植sync和sleep命令;

    3、编辑inittab初始化脚本在0级别的任务:

        vim /mnt/sysroot/etc/inittab添加

4:0:wait:/etc/rc.d/rc.sysdone

        测试新主机的关机功能:init 0

    4、编辑脚本实现新主机重启前要做的任务:

        cd /mnt/sysroot

        vim etc/rc.d/rc.reboot

#!/bin/bash

#

sync

sleep 1

sync

exec /sbin/reboot

        添加脚本执行权限:chmod +x  etc/rc.d/rc.reboot

    5、编辑inittab初始化脚本在6级别的任务:

        vim /mnt/sysroot/etc/inittab添加

l6:6:wait:/etc/rc.d/rc.reboot

        测试新重启的关机功能:init 6


如何做成执行对应级别下的服务脚本(如何实现一个脚本既能关机又能重启):

    6、做成规范的脚本

        cd /mnt/sysroot

        vim etc/rc.d/init.d/halt

#!/bin/bash

#

case $0 in 

*reboot)

COMMAND='/sbin/reboot';;

*halt)

COMMAND='/sbin/halt -p';;

*)

echo “Only call this script by *reboot OR *halt;”

;;

esac


case $1 in 

start)

;;

stop)

;;

*)

echo "Usage:`basename $0` {start|stop}"

;;

esac

exec $COMMAND

        添加脚本执行权限:chmod +x etc/rc.d/init.d/halt

    7、创建脚本链接:

        cd /mnt/sysroot/etc/rc.d

        ls

        ls init.d/

        mkdir rc0.d rc6.d

        cd rc0.d/

        ln -sv ../init.d/halt S99halt

        cd ../rc6.d

        ln -sv ../init.d/halt S99reboot

    8、***原来编辑的重启和关机脚本:

        cd ../

        rm -f rc.reboot rc.sysdone

        ls

        sync

    9、创建脚本实现把所有S开头的服务都start所有K开头的服务都stop:

        vim rc

#!/bin/bash

#

RUNLEVEL=$1

for I in /etc/rc.d/rc$RUNLEVEL.d/K*;do

$I stop

done


for I in /etc/rc.d/rc$RUNLEVEL.d/S*;do

$I start

done

        添加rc脚本执行权限:chmod +x rc

    10、编辑inittab文件:

        cd ../

        vim inittab修改为:

l0:0:wait:/etc/rc.d/rc 0

16:6:wait:/etc/rc.d/rc 6

        同步数据到磁盘:sync

    11、启动新主机验证:init 6 ; init 0 ;


实现对应3级别下的服务:

    12、添加3级别执行的脚本:

        vim /mnt/sysroot/etc/inittab添加:

l3:3:wait:/etc/rc.d/rc 3

    13、创建rc3.d目录:

        cd /mnt/sysroot/etc/rc.d

        mkdir rc3.d

    14、创建系统启动服务的调用脚本:

        vim init.d/tserver

#!/bin/bash

#

#chkconfig: 35 66 33                  -->调用的脚本

#description: test service script

#

prog=`basename $0`

lockfile=/var/lock/subsys/$prog


start() {

echo "Starting $prog ..."

touch $lockfile

}


stop() {

echo "Stopping $prog ..."

rm -f $lockfile

}


status() {

if [ -f $lockfile ];then

echo "Running..."

else

echo "Stopped..."

fi

}


usage() {

echo "Usage:$prog {start|stop|status|restart}"

}


case $1 in

start)

start;;

stop)

stop;;

restart)

stop

start

;;

status)

status;;

*)

usage

exit 1

;;

esac

        添加执行权限:chmod +x init.d/tserver

    15、在宿主机上运行脚本检测脚本是否能正常运行:

        init.d/tserver start

        ls -l /var/lock/subsys

        init.d/tserver stop

        ls -l /vat/lock/subsys

        init.d/tserver status

    16、在3级别下启动:

        cd rc3.d/

        ls

        ln -sv ../init.d/tserver S66tserver

        ll

    17、脚本中35级别为启动,那么06级别则为关闭:

        cd ..

        cd rc0.d/

        ln -sv ../init.d/tserver K33tserver

        cd ..rc6.d/

        ln -sv ../init.d/tserver K33tserver

        ll

    18、运行脚本binary移植basename:./binary.sh分别输入basename

    19、启动新主机测试,注意观察启动过程中文件系统报错"Filesystem Only-read";

        当运行init 3时,也报错"Filesystem Only-read"


实现在3级别下终端切换:

    20、修改级别3的启动终端脚本:

        cd /mnt/sysroot

        vim etc/inittab添加(man mingetty的用法):

1:2345:respawn:/sbin/mingetty --loginprog=/bin/bash tty1

2:2345:respawn:/sbin/mingetty --loginprog=/bin/bash tty2

    21、运行脚本binary移植mingetty:./binary.sh分别输入mingetty;

    22、创建bash环境:

        cd /mnt/sysroot/ 

        vim etc/rc.d/rc.sysinit***最后一行的/bin/bash

        cd /mnt/sysroot/bin

        ln -sv bash sh 

        ll

        sync

        sync

    23、启动新主机测试,屏幕显示"(none) login:",但ctrl+alt+F1|F2可实现终端切换;


解决新主机启动以读写方式挂载根文件系统:

    24、宿主机上修改系统挂载文件:

        cd /mnt/sysroot

        vim etc/fstab

/dev/hda2    /        ext3    defaults    0 0

/dev/hda1    /boot    ext3    defaults    0 0

proc        /proc     proc    defaults    0 0 

sysfs        /sys    sysfs    defaults      0 0 

        添加脚本执行权限:chmod +x etc/fstab

    25、实现开机自动挂载:

        vim etc/rc.d/rc.sysinit添加:

echo "Remount rootfs..."

mount -n -o remount,rw /

/bin/bash


解决新主机开机自动设置主机名:

    26、创建设置主机名文件:

        mkdir etc/sysconfig

        vim etc/sysconfig/network

HOSTNAME=minilinux.MegeEdu.com


    27、实现开机自动设置hostname:

        vim etc/rc.d/rc.sysinit添加:

echo "Set the hostname..."

[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network

[ -z $HOSTNAME -o "$HOSTNAME" == '(none)' ] && HOSTNAME=localhost

/bin/hostname $HOSTNAME

    28、测试:宿主机上切换chroot /mnt/sysroot,执行/etc/rc.d/rc.sysinit脚本测试是否有语法错误;


解决新主机让登录的问题(mingetty没有解决此问题):

        man agetty

        man stty,如:stty -F /dev/console size(当前使用的终端尺寸);stty -F /dev/console speed(当前使用的终端速率);

    29、重新修改inittab文件:

        vim etc/inittab修改其中的:

1:2345:respawn:/sbin/agetty -n -l /bin/bash 38400 tty1

2:2345:respawn:/sbin/agetty -n -l /bin/bash 38400 tty2


    30、运行脚本binary移植agetty:./binary.sh分别输入agetty


    31、sync

    32、启动测试新主机,注意观察如果没有异常那么登录问题解决;

    33、在此测试0级别下是否还有报错:init 0 。


按照RedHat的法则,实现当系统启动成功显示OK,当系统启动失败显示failure:

    34、编辑functions文件:

        cd /mnt/sysroot

        vim etc/rc.d/init.d/functions

#!/bin/bash

#

SCREEN=`stty -F /dev/console size 2> /dev/null`

COLUMNS=${SCREEN#* }

[ -z $COLUMNS ] && COLUMNS=80


SPA_COL=$[$COLUMNS-14]


RED='\033[31m'

GREEN='\033[32m'

YELLOW='\033[33m'

BLUE='\033[34m'

NORMAL='\033[0m'



success() {

string=$1 

RT_SPA=$[$SPA_COL-${#string}]

echo -n "$string"

for I in `seq 1 $RT_SPA`;do 

echo -n " " 

done

echo -e "[  ${GREEN}OK${NORMAL}  ]"

}


failure() {

string=$1 

RT_SPA=$[$SPA_COL-${#string}]

echo -n "$string"

for I in `seq 1 $RT_SPA`;do 

echo -n " "

done

echo -e "[  ${RED}FAILED${NORMAL}  ]"

}

        添加执行脚本权限:chmod +x etc/rc.d/init.d/functions

    35、修改系统启动服务的调用脚本:

        cd /mnt/sysroot/etc/rc.d

        vim init.d/tserver

#!/bin/bash

#

#chkconfig: 35 66 33                  

#description: test service script

#

. /etc/rc.d/init.d/functions


prog=tserver

lockfile=/var/lock/subsys/$prog


start() {

touch $lockfile

[ $? -eq 0 ] && success "Starting $prog" || failure "Starting $prog"

}


stop() {

rm -f $lockfile

[ $? -eq 0 ] && success "Stopping $prog" || failure "Stopping $prog"

}


status() {

if [ -f $lockfile ];then

echo "Running..."

else

echo "Stopped..."

fi

}


usage() {

echo "Usage:$prog {start|stop|status|restart}"

}


case $1 in

start)

start;;

stop)

stop;;

restart)

stop

start

;;

status)

status;;

*)

usage

exit 1

;;

esac

    36、执行脚本.binary.sh移植stty和seq命令

    37、切换,测试脚本运行:

        chroot /mnt/sysroot

        /etc/rc.d/init.d/tserver start


如何实现小系统能够获取IP地址:

    38、移植网卡模块:

        cd /mnt/sysroot

        mkdir lib/modules

        modinfo pcnet32   -->查看模块依赖和文件路径

        modinfo mii

        cp /lib/modules/2.6.18-348.el5/kernel/drivers/net/pcnet32.ko /mnt/sysroot/lib/modules

        cp /lib/modules/2.6.18-348.el5/kernel/drivers/net/mii.ko /mnt/sysroot/lib/modules

    39、自动装载网络模块:

        vim etc/rc.d/rc.sysinit添加:

echo "Initializing network device..."

/sbin/insmod /lib/modules/mii.ko

/sbin/insmod /lib/modules/pcnet32.ko


    40、创建网卡配置文件:

        mkdir -pv etc/sysconfig/network-scripts

        vim etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0

BOOTPROTO=static

IPADDR=172.16.100.5

NETMASK=255.255.0.0

GATEWAY=172.16.0.1

ONBOOT=yes

    41、创建脚本启动网卡:

        vim etc/rc.d/init.d/network

#!/bin/bash

#

prog=network


. /etc/rd.d/init.d/functions


CONF=/etc/sysconfig/network-scripts/ifcfg-eth0

. /CONF


NETMASK=16


start() {

ifconfig eth0 $IPADDR/$NETMASK up 

[ -z $GATEWAY ] && route add defaults gw $GATEWAY

}


stop() {

ifconfig eth0 down

}


status() {

ifconfig eth0

}


usage() {

echo "$prog: {start|stop|restart|status}"

}


case $1 in

start)

start

success "Config network card eth0"

;;

stop)

stop

success "Stop network card eth0"

;;

restart)

stop

start

success "Restart network card eth0"

;;

status)

status

;;

*)

usage

exit 1

;;

esac

        添加脚本执行权限:chmod +x etc/rc.d/init.d/network


    42、实现级别3下自动启动,级别0和级别6关闭:

        cd etc/rc.d/rc0.d/

        ln -sv ../init.d/network K90network

        cd ../rc6.d/

        ln -sv ../init.d/network K90network

        cd ../rc3.d 

        ln -sv ../init.d/network S09network

    43、编辑network脚本:

        cd ..

        ll

        vim init.d/network在第3和4行添加:

#chkconfig: 35 09 90

#description: network service

    44、启动新主机,测试效果;

        service network start

        ifconfig

        service network stop

        service network status

        ifconfig

        service network start


四、脚本编程知识点:

    1、变量中字符的长度:${#VARNAME},如:A="String Test";echo ${#A}

    2、获取屏幕的行和列的命令:stty -F /dev/console size

    3、获取列的命令:

        stty -F /dev/console size | cut -d' ' -f2

        stty -F /dec/console size | awk '{print $2}'

        A=`stty -F /dev/console size` && echo ${A#* } 


五、VM虚拟机环境,修复解决VM找不到inittab文件(虚拟主机文件系统错乱)的问题:

    1、打包所主机的/dev/hda2文件系统文件:

        cd /mnt/sysroot

        find . | cpio -H newc --quiet -o | gzip > /root/sysroot.gz 

    2、卸载/dev/hda2设备:

        umount /dev/hda2-->如果不能被卸载

        fuser -km /dev/hda2  -->强制卸载

        umount /dev/hda2

    3、修复/dev/hda2:

        e2fsck -f /dev/hda2

    4、重新挂载/dev/hda2:

        mount /dev/hda2 /mnt/sysroot/

    5、展开/dev/hda2文件系统:

        cd /mnt/sysroot

        zcat /root/sysroot.gz | cpio -id

    6、检查inittab文件:

        cat etc/inittab

    7、sync 

    8、如果仍然不能修复,那么备份/dev/hda2文件系统后格式化/dev/hda2,然后重新挂载到宿主机的/mnt/sysroot下即可。