精简linux内核实例及相关扩展

一个完整的linux系统所需最小条件:

/boot

grub

initrd.gz

vmlinuz(kernel)

...

/sysroot

init

linux常用目录

linux常用命令

...


创建精简内核实例:

1.磁盘分区并挂载

#fdisk /dev/sdb

/dev/sdb1

/dev/sdb2

#partprobe /dev/sdb

#mke2fs -j /dev/sdb1

#mke2fs -j /dev/sdb2

#mkdir /mnt/{boot,sysroot}

#mount /dev/sdb1 /mnt/boot

#mount /dev/sdb2 /mnt/sysroot


2.复制内核

#cp /boot/vmlinuz-xxxx /mnt/boot/vmlinuz


3.制作initrd.gz文件

#mkdir test

#cd test

#zcat /boot/initrd-`uname -r`.img | cpio -id

#vim init

mkrootdev -t ext3 -o defaults,ro /dev/sdb2

创建根设备

#resume LABLE=SWAP-sdaxx

因没有swap分区,所以注释掉此行。

注释掉不需要的模块。

...

cd lib/

#rm -r dm-* 删除dm文件,进一步缩小系统大小。

#find . | cpio -H newc --quiet -o |gzip -9 > /mnt/boot/initrd.gz 重新打包initrd文件。


4.安装grub并配置grub.conf

#grub-install --root-directory=/mnt /dev/sdb

#vim /mnt/boot/grub/grub.conf

default=0

timeout=5

title My Linux(KERNELVERSION)

root (hd0,0)

kernel /vmlinuz quiet

启动时不想显示启动信息使用quiet

initrd /initrd.gz


5.创建相关目录

#cd /mnt/sysroot

#mkdir -pv lib/modules bin sbin proc sys dev etc/rc.d/init.d root mnt media 

核心目录,不能单独分区。此时还没有root的概念,root文件夹其实可以单独分区。


#mkdir -pv root tmp home var/{log,run,lock/subsys,tmp} usr/{bin,sbin,local} opt boot 

非核心目录,可以单独分区。


6.编辑etc/inittab文件

#vim etc/inittab

id:3:initdefault:

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


7.复制相关模块的库。

#copy /lib/modules/KERNELVERSION/kernel/drivers/net/mii.ko /mnt/sysroot/lib/modules

#copy /lib/modules/KERNELVERSION/kernel/drivers/net/penet.ko /mnt/sysroot/lib/modules



8.编辑rc.sysinit文件并添加x权限。

#vim etc/rc.d/rc.sysinit

#!/bin/bash

echo -e "\tWelcom to \033[31mMY Team\033[0m Linux "

insmod /lib/modules/mii.ko

insmod /lib/modules/pcnet32.ko

ifconfig eth0 192.168.1.32/24

if lo 127.0.0.1/8

/bin/bash

#chmod +x etc/rc.d/rc.sysinit


9.使用copylib.sh脚本添加常用命令和相关库文件

#copylib.sh

init

bash

...


10.将以上操作写入硬盘保存。

#sync


11.使用chroot命令验证添加命令是否能正常工作

#chroot /mnt/sysroot

ls

...


扩展精简内核实例1:

0.此时系统根分区仍然为ro,修改为rw。此步骤在精简内核上执行。

#mount -n -o remount.rw /


1.编写关机脚本和重启脚本

#cd /mnt/sysroot

#vim etc/rc.d/rc.sysdone

#!/bin/bash

sync

sleep 5

sync

sleep 5

exec /sbin/halt -p

#chmod +x etc/rc.d/rc.sysdone


#vim etc/rc.d/rc,sysreboot

#!/bin/bash

sync

sleep 5

sync

sleep 1

exec /sbin/reboot

#chmod +x etc/rc.d/rc.sysreboot


2.添加常用命令

#bash copylib.sh

sync

sleep

ls

touch

mv

cp

vim

mount

umount

...


3.修改 etc/inittab文件,添加关机脚本。

#vim etc/inittab

id:3:initdefault:

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

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

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



扩展精简内核实例2:

将关机和重启写成一个脚本:

#copylib.sh

basename


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

#!/bin/bash

case $0 in

*reboot)

COMMAND=‘/sbin/reboot‘

;;


*halt)

COMMAND=‘/sbin/halt -p‘

;;

*)

echo "use *reboot or *halt"

;;

seca


case $1 in

start)

;;

stop)

;;

restart)

;;

status)

;;

*)

echo "`basename $0` {start|stop|restart|status}  "

;;

seca


esec $COMMAND


#chmod +x etc/rc.d/init.d/halt

#mkdir etc/rc.d/{rc0.d,rc6.d}

#ln -sv etc/rc.d/init.d/halt etc/rc.d/init.d/rc0.d/S99halt 

#ln -sv etc/rc.d/init.d/halt etc/rc.d/init.d/rc6.d/S99reboot

#vim etc/rc.d/rc

#!/bin/bash

RUNLEVEL=$1

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

if [-e /etc/rc.d/rc$RUNLEVNE.d/K*];then

$I stop

else

cuntinue

done


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

if [-e /etc/rc.d/rc$RUNLEVNE.d/S*];then

$I start

else

cuntinue

done

#chmod +x etc/rc.d/rc

#vim etc/inittab

id:3:initdefault:

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

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

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

#sync


扩展精简内核实例3:

在对应的级别上启动服务,例如3级别:

#vim etc/inittab

id:3:initdefault:

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

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

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

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


1:2345:respawn:/sbin/mingetty tty1

2:2345:respawn:/sbin/mingetty tty2



#cd etc/init.d/

#mkdir etc/rc.d/rc3.d

#vim tserver

#!/bin/bash

#chkconfig: 35 66 33

#description: test script

PROG=`basename $0`

LOCKFILE=/var/lock/subsys/$PROG

start(){

echo "starting $PROG"

touch $LOCKFIEL

}

stop(){

echo "stopping $PROG"

rm -f  $LOCKFIEL

}

status(){

if [-f $LOCKFILE] ;then

echo "$PROG is running"

else

echo "stoped"

fi

}

usage(){

echo "only use start|stop|restart|status!"

}


case $1 in

start)

start()

;;

stop)

stop()

;;

restart)

stop()

start()

;;

stop)

stop()

;;

*)

usage()

;;

exit 1

esca

#chmod +x tesrver

#cd rc3.d

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

#ln sv etc/initd/tserver etc/init.d/rc0.d/K33tserver

#ln sv etc/initd/tserver etc/init.d/rc6.d/K33tserver

#bash copybin.sh

mingetty

basename

#sync



扩展精简内核实例4:

此时3模式还无法启动,因为在rc.sysinit中已经执行了/bin/bash,不会进入3模式。同时此时根文件系统仍为ro,无法创建锁文件。修复此问题。同时给系统写入主机名。

#vim etc/inittab

id:3:initdefault:

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

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

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

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


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

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


#vim etc/rc.d/rc.sysinit

#!/bin/bash

echo -e "\tWelcom to \033[31mMY Team\033[0m Linux "

echo "remontu rootfs"

mount -n -o remount,rw /

echo "setting the hostname"

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

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

/bin/hostname $HOSTNAME

insmod /lib/modlues/mii.ko

insmod /lib/modlues/pcnet32.ko

ifconfig eth0 192.168.1.32/24

if lo 127.0.0.1/8

#bash copybin.sh

mingetty

hostname

agetty


#cd /mnt/sysroot/bin

#ln -sv bash sh

#cd /mnt/sysroot

#vim etc/fstab

/dev/hda2 / ext3 defaults 0 0

/dev/sda1 /boot ext3 defaults 0 0

proc /proc proc defaults 0 0

sysfs /sys sysfs defaults 0 0

#mdkir etc/sysconfig

#vim etc/sysconfig/network

HOSTNAME=mylinux.com

#sync


扩展精简内核实例5:

接上个扩展,此时由于编辑太频繁导致系统损坏,进行文件系统修复:

#cd /mnt/sysroot

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

#fuser -km /dev/sdb2

#umonut /dev/sdb2

#mke2fs -j /dev/sdb2 

#mount /dev/sdb2 /mnt/sysroot

#cd /mnt/sysroot

#zcat /root/sysroot.gz| cpio -id

#sync


也可以在umount以后使用e2fsck修复。

#e2fsck -af /dev/sdb2

#cat  etc/inittab 检查inittab文件是否损坏。

#sync


扩展精简内核实例6:

使用公共脚本来完善功能,让tserver启动或关闭时显示正常系统提示ok或者是failuer。公共脚本位置/etc/rc.d/init.d/functions。

#copybin.sh

seq

stty


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

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

COLNUM=${SCREEN#* }

[-z $COLNUM] && COLNUM=80

SPA_COL=$[$COLNUM-14]

这里的12是[  \033[1;32mfailure\033[0m  ]的字符长度。这部分长度是固定的。[  \033[1;32mOK\033[0m  ]长度为8个字符。


RED=‘\033[31m‘

GREEN=‘\033[32m‘

YELLOW=‘\033[33m‘

BLUE=‘\033[34m‘

NORMAL=‘\033[0m‘


scuess(){

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}  ]"

}


failuer(){

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}  ]"

}

#vim etc/rc.d/init.d/tserver

#!/bin/bash

#chkconfig: 35 66 33

#description : test script

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


PROG=tserver

LOCKFILE=/var/lock/subsys/$PROG

start(){

touch $LOCKFIEL

[$? -eq 0] && success() "Starting $PROG" || failuer "Starting $PROG"

}

stop(){

rm -f  $LOCKFIEL

[$? -eq 0] && sucess() "Stopping $PROG" ||failuer "Stopping  $PROG"

}

status(){

if [-f $LOCKFILE] ;then

echo "$PROG is running"

else

echo "stoped"

fi

}

usage(){

echo "only use start|stop|restart|status!"

}


case $1 in

start)

start()

;;

stop)

stop()

;;

restart)

stop()

start()

;;

stop)

stop()

;;

*)

usage()

;;

exit 1

esca

#sync


扩展精简内核实例7:

使用脚本为精简系统增加ip地址。原来是通过在etc/rc.d/rc.sysinit中直接写入的方式。

第7步中已经将pcnet32.ko和mii.ko复制到/mnt/sysroot/lib/modules内。

#vim etc/rc.d/rc.sysinit

#!/bin/bash

echo -e "\tWelcom to \033[31mMY Team\033[0m Linux "

echo "remontu rootfs"

mount -n -o remount,rw /

echo "setting the hostname"

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

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

/bin/hostname $HOSTNAME

echo "Initializing network device ..."

/sbin/insmod /lib/modlues/mii.ko

/sbin/insmod /lib/modlues/pcnet32.ko


#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


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

#chkconfig 35 09 90

#description: network service

#!/bin/bash

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

. $FILE

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

PROG=network


start(){

ifconfig eth0 $IPADDR $NETMASK up

[-z $GATEWAY] && router add default gw $GATEWAY

return 0

}


stop(){

ifconfig eth0 down

}


status(){

ifconfig eth0

[$? -eq 0] && echo "eth0 is ok"


}


usage(){


echo "$PROG use start|stop|restart|status]"

exit 1

}


case $1 in

start)

start() 

success() "config network eth0 "

;;

stop)

stop()

success() "stop network eth0"

;;

restart)

stop()

start()

success() "restart network eth0"

status)

status()

;;

*)

usage()

;;


seca

#cd etc/rc.d/rc0.d

#ln -sv etc/rc.d/init.d/network K90network

#cd etc/rc.d/rc6.d

#ln -sv etc/rc.d/init.d/network K90network

#cd etc/rc.d/rc3.d

#ln -sv etc/rc.d/init.d/network S09network

#sync

此脚本仍然无法启动网卡,因为ifconfig接受子网掩码格式为IP/NETMASK,所以从文件中读取的信息不可用。可以手工指定。


扩展精简内核实例8:

创建系统启动后在登录账号前显示的终端提示信息。

#cp /etc/issue /mnt/sysroot/etc/

#vim /mnt/sysroot/etc/issue


扩展精简内核实例9:

实现挂载额外的文件系统。

系统启动时,/ /proc /sysfs都是自动挂载的。/etc/fstab中其他的文件系统都未自动挂载。当前已挂载的可以从/proc/mounts中查看。


#vim etc/rc.d/rc.sysinit

#!/bin/bash

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


echo -e "\tWelcom to \033[31mMY Team\033[0m Linux "


echo "remontu rootfs"

mount -n -o remount,rw /

[$? -eq 0] && success() "Remount rootfs"||failuer() "Remount rootfs"

mount -a

grep -E -v "\<swap|proc|sysfs|\/dev\/mapper\>" /etc/fstab |awk ‘{print $1}‘|

while read LINE;do

awk ‘{print $1}‘ /proc/mounts|grep "^$LINE$"

if [ $? -eq 0 ] ;then

success() "$LINE mount "

else

failure() "$LINE mount"

fi

done


echo "setting the hostname"

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

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

/bin/hostname $HOSTNAME

[$? -eq 0] && success() "Setting Hostname"||failuer ()"Setting Hostname"


echo "Initializing network device ..."

/sbin/insmod /lib/modlues/mii.ko

[$? -eq 0] && success() "loading mii.ko"||failuer() "loading mii.ko"

/sbin/insmod /lib/modlues/pcnet32.ko

[$? -eq 0] && success() "loading penet32.ko"||failuer() "loading penet32.ko"


扩展精简内核实例10:

设定内核参数。配置文件为/etc/sysctl.conf,使用sysctl -p令配置生效。 

#copylib.sh

sysctl

#vim etc/sysctl.conf

net.ipv4.ip_forward=1


#vim etc/rc.d/rc.sysinit

#!/bin/bash

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


echo -e "\tWelcom to \033[31mMY Team\033[0m Linux "


echo "remontu rootfs"

mount -n -o remount,rw /

[$? -eq 0] && success() "Remount rootfs"||failuer() "Remount rootfs"

mount -a

grep -E -v "\<swap|proc|sysfs|\/dev\/mapper\>" /etc/fstab |awk ‘{print $1}‘|

while read LINE;do

awk ‘{print $1}‘ /proc/mounts|grep "^$LINE$"

[ $? -eq 0 ] && success() "$LINE mount "||failure() "$LINE mount"

done


echo "setting the hostname"

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

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

/bin/hostname $HOSTNAME

[$? -eq 0] && success() "Setting Hostname"||failuer ()"Setting Hostname"


echo "Initializing network device ..."

/sbin/insmod /lib/modlues/mii.ko

[$? -eq 0] && success() "loading mii.ko"||failuer() "loading mii.ko"

/sbin/insmod /lib/modlues/pcnet32.ko

[$? -eq 0] && success() "loading penet32.ko"||failuer() "loading penet32.ko"


sysctl -p &> /dev/null

[ $? -eq 0] && success "setting kernel parameter"||failuer "setting kernel parameter"


扩展精简内核实例11:

用户账号登陆相关。

跳过PAM认证。

0.重新编译/mnt/sysroot/bin/login,跳过PAM验证。

暂时不会,等待后续添加。


1.复制nssswitch所需的库文件

#cp -d /lib/libnss_files* /mnt/sysroot/lib

#cp -d /lib/libnss_files.so /mnt/sysroot/usr/lib

#cp -d /usr/libness3.so /mnt/sysroot/usr/lib

#cp -d /usr/libnessckib.so /mnt/sysroot/usr/lib

#cp -d /usr/libnessutil3.so /mnt/sysroot/usr/lib

2.编辑配置/etc/nsswitch.conf

#cp /etc/nsswitch.conf /mnt/sysroot/etc

#vim /mnt/sysroot/etc/nsswitch.conf

passwd: files

shadow: files

group: files

hosts: files dns


3.创建用户:

#vim /mnt/sysroot/etc/passwd

#vim /mnt/sysroot/etc/shadow

#vim /mnt/sysroot/etc/group


4.移植mingetty等相关库,此时可以不在使用agetty。

passwd等命令依靠PAM,所以作用不大。

#bash copylib.sh 

mingetty

passwd

useradd

usermod

userdel

usermod

login

groupadd

...

5.修改/mnt/sysroot/etc/inittab,将agetty替换成mingetty

#vim /mnt/sysroot/etc/inittab

id:3:initdefault:

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

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

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

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


1:2345:respawn:/sbin/mingetty /bin/bash 38400 tty1

2:2345:respawn:/sbin/mingetty /bin/bash 38400 tty2


6.设置账号登陆后,用户的环境变量:

#vim /mnt/sysroot/root/.bash_profile

export PS1=‘[\u@\h \W]\$‘

7.设置/root目录权限

#chmod -R og=--- /mnt/sysroot/root




扩展精简内核实例12:

单用户模式

1.修改/etc/inittab文件,增加1级别。

#vim /mnt/sysroot/etc/inittab

id:3:initdefault:

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


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

l1:1:wait:/etc/rc.d/rc 1

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

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


1:2345:respawn:/sbin/mingetty /bin/bash 38400 tty1

2:2345:respawn:/sbin/mingetty /bin/bash 38400 tty2

2.创建1模式下的相关脚本

#cd /mnt/sysroot/etc/rc.d/init.d

#mkdir rc1.d

#cd rc1.d

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

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

3.编辑1模式的脚本

#vim /mnt/sysroot/etc/rc.d/init.d/single

#!/bin/bash

#chkconfig:

#description:

case $1 in

start)

;;

*)

echo "usage:single start" 

esca

exec /sbin/init S

#chmod +x /mnt/sysroot/etc/rc.d/init.d/single

#ln -sv /mnt/sysroot/etc/rc.d/init.d/single /mnt/sysroot/etc/rc.d/rc1.d/S99single

#sync


4.开机后在grub中进入单用户模式

按e键进行编辑启动条目,再按e键编辑kernel项,在后边输入1后回车,按b键引导。


/etc/issue

提供系统启动后在登录账号前显示的相关信息。

常见的逃逸字符含义:

mingetty:

\r 显示系统的发行号,相当于uname -r

\m 显示机器的平台架构,相当于uname -m


其他类似agetty等也有类似的逃逸字符定义,使用前先用man文档查看相关内容。



copylib.sh脚本:复制命令及相关的库文件。

/root/copylib.sh

#!/bin/bash

DEST=/mnt/sysroot

libcp(){

LIPPATH=${1%/*}

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

[!-e $DEST${1}] && cp $1 $DEST$LIBPAHT && echo "copy lib $1 ok"

}


bincp(){

CMDPAHT=${1%/*}

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

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


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 "cppy $COMMAND finished"

read -p "continue:"CMD

done


PAM:Pluggeable Authentication Module 可插入式认证模块。

配置文件:/etc/pam.d/*


nsswitch:Network Service Switch 网络服务切换。是一个中间层框架。

库:

/lib/libnss*.so

/usr/lib/libnss*.so

配置文件:

/etc/nsswitch.conf



本文出自 “小私的blog” 博客,请务必保留此出处http://ggvylf.blog.51cto.com/784661/1615045

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。