linux的裁剪過程,讓你的小linux更加完善,趕快試試吧!
一、系統啓動流程:
1、POST-->BIOS(Boot Sequence)--> BootLoader(MBR)--> Kernel(initrd,initramfs)--> init (/etc/inittab)
第一步首先加電自檢,計算機本身不會執行程序,由此它會載入一段程序,它會在開機時自動實現將某個RAM中的程序映射到cpu可以尋址的地址空間中去,並且可以讓cpu可以執行其中的指令,而這些指令是完成系統檢測的,檢測完成之後,當所有的硬件或基本的核心硬件沒有問題的話就進行BIOS。根據BIOS中所設定的程序啓動流程去找與其對應設備上的MBR,按照引導次序執行(Boot Sequence),根據引導次序逐個查找對應的存儲設備上的MBR,若MBR存在,則讀取MBR上的BootLoader,BootLoader是一段程序,早期的MBR總共512字節,但它留給BootLoader空間大小是446字節,在BootLoader當中配置了所有引導的操作系統的內核的位置,因此BIOS在載入內存以後,當它實現將控制流程或控制權限轉交給BootLoader以後,BootLoader就接收了整個系統的控制權限,而後根據用戶的選擇,去讀取相應操作系統的內核。第三步:將內核裝載進內核中合適的位置,解壓縮並完成內核初始化,BootLoader會把控制權限轉交給內核。第四步:如果內核訪問根文件系統的設備需要用到某個驅動程序,而內核中也沒有,就需要到根文件中去找這個驅動程序,但這文件系統本身又沒有掛載,因此要想訪問根文件系統得先找到驅動,要訪問驅動得先找到根文件系統,這就出現了一個難題,這時就要藉助於initrd,爲內核提供訪問真正的根文件系統所需要的基本驅動程序。因此initrd是一個輔助性的、過渡性的中間層。它能夠實現將kernel與真正的根文件系統連接起來,當連接完成之後它就沒有任何意義了。第五步:執行init進程,而init程序本身的配置文件是/etc/inittab(而在紅帽6上init不在是傳統的init,而是upstart,而upstart的配置文件在/etc/inittab和/etc/init/.*conf下的所有文件
2、(kernel)內核初始化:
硬件探測
裝載驅動
掛載根文件系統(rootfs)
啓動用戶空間中的第一個進程init
3、init所要完成的工作主要取決於/etc/inittab,而 /etc/inittab所要完成的任務有很多:設定默認運行級別;系統初始化腳本(/etc/rc.d/rc.sysinit);運行指定級別的服務腳本:/etc/rc.d/init.d/。連接到:/etc/rc.d/rc#.d(rc0.d--rc6.d),而鏈接文件比較獨特,有的是以K開頭的文件,有的是以S開頭的文件,這兩種文件的後面都跟有一個數字(00-99),而這些數字是運行次序或者說是執行次序。一般來說數字越小,運行級別越高(越先被執行)。而這些鏈接文件都是通過chkconfig實現的。run運行指定級別的腳本完成之後,設定Ctrl、Alt、Delete三個鍵的意義,還有設定突然斷電時怎麼辦?電源又恢復的時候怎麼辦?但這些任務對我們來說並不是最關鍵的,接下來啓動虛擬終端、啓動圖形終端
4、/etc/rc.d/rc.sysinit:系統初始化,大概執行以下任務:(注意:內核在裝載根文件系統時爲了避免文件損壞,是以只讀方式掛載的)
檢測並以讀寫方式重新掛載根文件系統;設定主機名;檢測並掛載/etc/fstab中的其它文件系統;啓動swap分區;初始化外圍硬件設備的驅動;根據/etc/sysctl.conf設定內核參數;激活udev和selinux;激活LVM和RAID設備;清理過期鎖和PID文件;裝載鍵映射;
二、製作自己的小linux:
1、學了那麼久的linux了,我們也應該有一個屬於自己製作的小linux了,而小linux所要實現的功能有一下幾部分:
1)、關機和重啓;shutdown -r now 重啓;shutdown -h now:關機; halt關機; reboot重啓; poweroff關機
2)、主機名;
3)、運行對應服務腳本;
4)、啓動終端;
5)、運行用戶;
6)、定義單用戶級別;
7)、裝載網卡驅動,啓用網絡功能;
8)、提供一個web服務器;
9)、設定內核參數;
這些做完後我們的小linux就算是真正的完成了,但我們發現這個小linux每用到一個命令都要移植,這是比較麻煩的,因爲你不僅要移植命令還要移植文件所依賴的庫,那接下來我們就做到linux真正的裁剪和定製。
2、我們有一個項目叫busybox,它是一個命令也是一個二進制程序,但是他有很多鏈接,不到1M大小,一個命令可以模擬幾百個命令使用,例如你拿它當ls用,它就是ls等等、、、、我們可以使用一個1M的busybox手動製作一個內核(kernel),因此我們不需要移植太多的模塊,只需要移植一些最最基本的就可以了。
下面我們就來製作一個屬於自己的小linux
開始之前先把虛擬機安裝好,這裏我用的是linux-5.8的版本,安裝好後,再添加一個盤進來,爲了便於區別我安裝了一塊IDE的盤
1、創建分區(在這裏我們創建2個2G的主分區)
partprobe /dev/hda #重讀磁盤分區
cat /proc/partitions #查看分區列表
2、創建掛載點,mkdir /mnt/{boot,sysroot}其中hda1掛載在/mnt/boot;hda2掛載在/mnt/sysroot
mkdir /mnt/{boot,sysroot} -pv # 創建掛載點
mke2fs -j /dev/hda1 #格式化
mke2fs -j /dev/hda2
mount /dev/hda1 /mnt/boot #掛載設備
mount /dev/hda2 /mnt/sysroot
mount #查看是否掛載成功
3、切記雖然掛載好了,但掛載點裏面沒有任何文件,下面我們複製內核
cp /boot/vmlinuz-2.6.18-308.el5 /mnt/boot/vmlinuz
爲了便於解壓縮,我在這裏建一個test目錄
mkdir test
cd test
zcat /boot/initrd-2.6.18-308.el5.img | cpio -id
vim init #編輯配置文件
cd lib/ #裏面有很多的dm模塊,沒有用,就刪了
rm -f dm-* #刪除dm開頭的模塊文件
find . | cpio -H newc --quit -o | gzip -9 > /mnt/boot/initrd.gz #(先備份出來)
ls -lh /mnt/boot/ #檢驗
grub-install --root-directory=/mnt /dev/hda #安裝grub
ls /mnt/boot #校驗一下是否有grub
vim /mnt/boot/grub/grub.conf #編輯配置文件
default=0
timeout=5
title my linux(2.6.18)
root (hd0,0)
kernel /vmlinuz
initrd /initrd.gz
提供真正的根文件系統
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 #創建所需的根文件系統
vim etc/inittab # 編輯配置文件
id:3:initdefault: #設定默認運行級別
si::sysinit:/etc/rc.d/rc.sysinit #系統初始化腳本
vim etc/rc.d/rc.sysinit #編輯編輯初始化腳本
#!/bin/bash
echo -e "\tWelcome to \033[1;34mMagedu linux\033[0m"
/bin/bash #執行/bin/bash
chmod +x etc/rc.d/rc.sysinit #給配置文件執行權限
複製命令的腳本:在根目錄下編輯bincp.sh
vim bincp.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 &> /dev/null && 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 bincp.sh #給文件執行權限
複製這些命令:init,bash,ls,touch,mkdir,cat ,mount,umount,vim,vi,chmod,chown,cp,ping,route,reboot,halt,shutdown,hostname,注意每添加一個命令都要複製過來
sync(多同步幾次)
驗證:
4、新建一個虛擬機,使用我們剛纔添加的IDE盤,驗證一下看能否啓動:
注意:啓動小linux完成之後它無法自動完成將根文件系統掛載可讀寫
而mount –n:掛載時不更新/etc/mtab文件
我們在touch一個文件:
5、現在這個小系統還不能關機,重啓,接下來我們就讓它可以實現關機,重啓的功能:切回到宿主機:給我的小系統提供腳本,來實現系統關機、重啓的功能
cd /mnt/sysroot
etc/rc.d/rc.sysdone #腳本,可用於實現微型的Linux系統關機
#!/bin/bash
#
sync
sleep 2
sync
mount | awk '{print $3}' | grep -v -E "\/(dev|proc|sys)?$" | sort -r | while read LINE; do
umount -n -f $LINE
[ $? -eq 0 ] && echo "Unmount $LINE finished." || echo "Can not unmount $LINE."
done
mount | awk '{print $3}' | while read LINE; do
mount -n -o remount,ro $LINE
[ $? -eq 0 ] && echo "Remount $LINE finished." || echo "Can not remount $LINE."
done
exec /sbin/halt -p
chmod +x etc/rc.d/rc.sysdone #給腳本一個執行權限
注意每添加一個命令都要通過bincp.sh腳本複製過去
vim etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/rc.sysinit
l0:0:wait:/etc/rc.d/rc.sysdone #切換到0級別時要執行/etc/rc.d/rc.sysdone
l6:6:wait:/etc/rc.d/rc.reboot #切換到6級別時要執行/etc/rc.d/rc.reboot
vim etc/rc.d/rc.reboot #編輯reboot腳本(重啓腳本)
#!/bin/bash
#
sync
sleep 1
sync
exec /sbin/reboot #執行這個腳本
chmod +x etc/rc.d/rc.reboot #給執行權限
vim etc/rc.d/rc.sysdone #關機腳本
#!/bin/bash
#
sync
sleep 2
sync
exec /sbin/halt -p
chmod +x etc/rc.d/rc.sysdone
驗證關機與重啓功能:
注意:注意如果在此處修改小系統,再回到宿主機,系統可能會崩潰,如果崩潰就用下面的命令修復
cd /mnt/sysroot/
find . | cpio -H newc --quiet -o | gzip > /root/sysroot.gz(把所有的大小打包起來)
cd
umount /mnt/sysroot(若卸不掉就使用fuser -km /dev/hda2)
mke2fs -j /dev/hda2 #重新格式化
mount /dev/hda2 /mnt/sysroot/ #重新掛載
cd /mnt/sysroot
zcat /root/sysroot.gz | cpio -id (展開所有打包的文件)
sync(多執行幾次)
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
爲halt創建鏈接:
cd etc/rc.d/
mkdir rc0.d rc6.d #創建兩個目錄
cd rc0.d/
ln -sv ../init.d/halt S99halt
cd ..
cd rc6.d/
ln -sv ../init.d/halt S99reboot
而rc.reboot rc.sysdone這時已經沒用了,那我們就把它刪了
rm -rf rc.sysdone rc.reboot
創建rc腳本:把所有S開頭的都start,把所有K開頭的都stop
vim etc/rc.d/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
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
l3:3:wait:/etc/rc.d/rc 3 #爲3級別創建目錄
l6:6:wait:/etc/rc.d/rc 6
cd etc/rc.d/
mkdir rc3.d
vim etc/rc.d/init.d/tserver #腳本,測試SysV服務的定義格式:
#!/bin/bash
#
# chkconfig: 35 66 33 #通過chkconfig控制
# 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 "Staring $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
chmod +x init.d/tserver
cd rc3.d #爲3級別創建鏈接文件
ln -sv ../init.d/tserver S66tserver
ln -sv ../init.d/tserver S33tserver
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
注意每添加一個功能都要在小系統中驗證一下
7、要想讓根文件系統重新掛載可讀寫,先編輯etc/fstab配置文件
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
vim etc/rc.d/rc.sysinit
#!/bin/bash
#
echo -e "\tWelcome to \033[34mMageEdu\033[0m Linux"
echo "Remount rootfs..."
mount -n -o remount,rw /
echo "Set 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/modules/mii.ko #cp 模塊以後添加進來
/sbin/insmod /lib/modules/pcnet32.ko
mkdir etc/sysconfig
vim etc/sysconfig/network
HOSTNAME=minilinux.magedu.com #添加主機名
vim etc/rc.d/init.d/functions 可用於控制服務腳本的信息顯示:
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} ]"
}
mkdir lib/modules #創建模塊文件
cp /lib/modules/2.6.18-308.el5/kernel/drivers/net/pcnet32.ko/mnt/sysroot /lib/modules
cp /lib/modules/2.6.18-308.el5/kernel/drivers/net/mii.ko /mnt/sysroot/lib/modules/
8、添加IP地址
mkdir -pv etc/sysconfig/network-scripts #先創建目錄
vim etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
IPADDR=192.168.1.150
NETMASK=255.255.255.0
GATEWAY=172.16.0.1
ONBOOT=yes
vim etc/rc.d/init.d/network
#!/bin/bash
#
#chkconfig: 35 09 90
#description: network service
prog=network #定義變量
./etc/rc.d/init.d/functions #調用函數
CONF=/etc/sysconfig/network-scripts/ifcfg-eth0
.$CONF
start() {
ifconfig eth0 $IPADDR/16 up
[ -z $GATEWAY ] && route add default gw $CATEWAY
}
stop() {
ifconfig eth0 down
}
status() {
ifconfig eth0
}
usage() {
echo "$prog:{start|stop|restart|status}"
}
case $1 in
start)
success "Config network eth0" ;;
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 #執行權限
要想能在級別0,3,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
用戶登陸時顯示的信息設置
vim /mnt/sysroot/etc/issue 添加如下內容
My Linux
Kernel \r on an \m #內核版本號
設定內核參數:
vim /mnt/sysroot/etc/sysctl.conf 內容如下:
net.ipv4.ip_forward = 1
編輯/mnt/sysroot/etc/rc.d/rc.sysinit文件 添加以下內容
sysctl -p &> /dev/null #IP地址立即生效
9、添加用戶功能
使用不依賴與PAM的login程序
放到/mnt/sysroot/bin/目錄下,之後賦予它執行權限
登陸時是使用login程序來驗證登陸的,實現用戶認證是到特定的文件中去認證的,傳統的方式都是
放在/etc/passwd以及/etc/shadow
nsswitch是個框架,它能夠完成配置到哪個去找用戶的賬號及密碼;nsswitch就是依靠配置文件來定義的
nsswitch這個框架由庫和相對應的配置文件來組成,在配置文件中可直接定義基於哪個庫去去找相應的驗證文件
例如:在/ect/passwd認證所找的是libnss_file.so這樣的庫
vim /mnt/sysroot/etc/nsswitch.conf 內容如下:
passwd: files
shadow: files
group: files
hosts: files dns
複製庫文件
cp -d /lib/libness_file* /mnt/sysroot/lib/
cp -d /usr/lib/libnss_files.so/mnt/sysroot/usr/lib/
cp -d /usr/lib/libnss3.so /usr/lib/libnssckbi.so /usr/lib/libnssutil3.so /mnt/sysroot/lib/
創建用戶
這裏直接從本系統上覆制一個用戶過來
grep -E "^root\> /etc/passwd > /mnt/sysroot/etc/passwd
grep -E "^root\> /etc/shadow > /mnt/sysroot/etc/shadow
grep -E "^root\> /etc/group> /mnt/sysroot/etc/group
修改inittab文件,現在可以改爲讓輸入用戶的登陸方式了
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 tty1
2:2345:respawn:/sbin/mingetty tty2
到這裏用戶功能的添加就完成了。
補充:
對/mnt/sysroot/etc/rc.d/rc.sysinit配置的整體修改,來實現對界面的進一步美化,代碼如下:
#!/bin/bash
#
. /etc/rc.d/init.d/functions
echo -e "\tMy\033[34mMagedu.com\033[0mLinux"
echo "Remount rootfs...."
mount -n -o remount,rw /
[ $? -eq 0 ] && success "Remount rootfs" || failure "Remount rootfs"
mount -a
[ $? -eq 0 ] && success "Mount others filesystem" || failure "Mount others filesystem"
#Set the hostname.....
[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network
[ -z $HOSTNAME -o "$HOSTNAME" == '(none)' ] && HOSTNAME=localhost
/bin/hostname $HOSTNAME
[ $? -eq 0 ] && success "Set the hostname" || failure "Set the hostname"
# Initializing network device....
/sbin/insmod /lib/modules/mii.ko
/sbin/insmod /lib/modules/pcnet32.ko
[ $? -eq 0 ] && success "Initializing network device" || failure "Initialization network device"
ifconfig lo 127.0.0.1/8
[ $? -eq 0 ] && success "Activating loopback network device" || failure "Activating loopback network device"
sysctl -p &> /dev/null
[ $? -eq 0 ] && success "Set kernel parameter" || failure "Set kernel paramenter"
屬於自己的小linux就做好了,雖然不是很完善,但是也很好用的,趕快試試吧!