1.引言
本文著(zhù)重講述如何制作基于linux的usb啟動(dòng)盤(pán),此usb啟動(dòng)盤(pán)能夠實(shí)現以下功能。
a. usb啟動(dòng)盤(pán)的Linux內核usblinux.kernel應支持盡可能多的硬件(包括硬盤(pán)驅動(dòng),網(wǎng)卡驅動(dòng),usb驅動(dòng))
b. u盤(pán)根文件系統放在ramdisk中,啟動(dòng)之后解壓到ram中。
c. usb啟動(dòng)盤(pán)啟動(dòng)之后能夠在目標機上執行分區(fdisk),格式化(mkfs.*)以及在各種塊設備上安裝grub
d. usb啟動(dòng)盤(pán)能夠臨時(shí)充當局域網(wǎng)內的網(wǎng)關(guān)。
e. usb啟動(dòng)盤(pán)能夠在一臺機器上快速的搭建網(wǎng)關(guān)服務(wù)器。
2.定制操作系統所要考慮的事情
不管是在u盤(pán)上面還是在其他存儲設備上(硬盤(pán),軟盤(pán))安裝Linux,我們所需要考慮的事情基本一樣。
1)定制自己的內核(包括選定確當的內核版本,內核是否支持模塊等等)
2) 定制自己的根文件系統(包括根文件系統的架構,根文件系統的內容,根文件系統所采用的文件系統類(lèi)型等等)
3) 配備引導加載程序(bootloader)
3. UsbLinux 的系統架構
結合1和2我們現在來(lái)具體定制我們的UsbLinux。
1) 內核選用
2) 內核支持模塊加載功能,上面說(shuō)了我們的內核應該盡可能支持多的硬件,如果我們把這些硬件的驅動(dòng)全部靜態(tài)編譯進(jìn)內核的話(huà),內核將會(huì )變的非常龐大,這是我們不希望看到的,這不僅僅會(huì )減慢Usblinux啟動(dòng)的速度,而且我們不能動(dòng)態(tài)的去除不必要的內核模塊。
3) 根文件系統選擇ext2文件系統,前面說(shuō)了我們的根文件系統是放在ramdisk中的,ramdisk正如其名,存在于ram中并且功能猶如塊設備。因此也就決定了根文件系統里面的東西修改之后斷電不能保存,ext2文件系統的特性主要包括可讀寫(xiě),可壓縮,不具備斷電可靠性,ext3,reiserfs等日志文件系統是具備斷電可靠性的,它們用在硬磁盤(pán)上比較合適。我們這里的根文件系統存放在ram中,因此選用ext2文件系統比較合適。
4) bootloader 選擇grub,我們不是在搞嵌入式所以grub是一個(gè)非常好的選擇。
說(shuō)明:下面的所有操作都是在red hat linux 9里面完成的。
4. 編譯安裝內核
4.1. 選擇配置內核方式
配置內核有多種方法,切換到源碼目錄下,
a. make oldconfig,make config(注,除非你很喜歡這種配置方式,否則建議你還是不要使用它們,它們不但不直觀(guān),而且配置容易出錯)
b.make menuconfig,這是最常用的一種配置方法,方便直觀(guān)。如果沒(méi)有其它特殊原因,建議你使用這種配置方法。
c.make xconfig, 這個(gè)需要X窗口的支持,如果你喜歡這個(gè)配置方法也很方便
4.2. 內核配置
這當然是很重要的一個(gè)步驟了,關(guān)于配置內核的具體細節網(wǎng)上有很多這樣的文章,這里只重點(diǎn)說(shuō)以下幾個(gè)重要的地方。
Loadable module support: 這個(gè)我們支持,因為我們的驅動(dòng)大多是編譯成模塊方式的。
Process type: 由于我們的UsbLinux是做成通用的而不是針對某個(gè)目標機的,所以處理器的選擇至關(guān)重要,為什么這樣說(shuō)呢? 如果你的內核選擇的處理器類(lèi)型是的Athlon/Duron ,那么在一臺386或者586的機器上到解壓內核的時(shí)候可能會(huì )出問(wèn)題,我試了在奔騰或者賽楊的處理器上也是到解壓內核的時(shí)候就停在那邊了。我們現在的處理器大多是X86系列的,因此處理器選擇386,可以避免上述的麻煩,當然針對具體的機器這個(gè)必然會(huì )對機器的性能產(chǎn)生影響。
Block devices: 一定要選擇ram disk support 和initrd support
NetWorking options: 這里面的是關(guān)于內核支持的網(wǎng)絡(luò )功能,我們的UsbLinux需要臨時(shí)充當網(wǎng)關(guān),而且能夠利用它搭建網(wǎng)關(guān)服務(wù)器,因此這里面的大多數選項都要選,這里面的選項比較多,最好對網(wǎng)絡(luò )方面的知識有個(gè)大概的了解。
ATA/IDE support: 硬盤(pán)的類(lèi)型,這個(gè)里面也有比較多的硬盤(pán)型號,我們現在大多是IDE硬盤(pán),但是如果你想讓你的UsbLinux的通用性好一些的話(huà),最好上網(wǎng)查查硬盤(pán)廠(chǎng)商的相關(guān)資料。
SCSI support:
盡管現在很少見(jiàn)到SCSI的硬盤(pán),不過(guò)我們還不得不讓內核支持SCSI,為什么呢? linux把usb設備是當成SCSI看待的,因要支持USB就要支持SCSI才行。具體的把下面這兩個(gè)選項編譯進(jìn)內核就可以了,其它的基本上用不著(zhù)。
<*>SCSI Support
<*>SCSI Disk Support
另外為了在vmware上面測試,我把BusLogic這個(gè)驅動(dòng)編譯進(jìn)了內核。
NetWork Devices Support:
網(wǎng)絡(luò )設備支持,我們基本上只需要選擇Ethernet(10 or 100Mbit)這里面的選項就可以了,其它的千M以太網(wǎng)卡,FDDI以及PPP之類(lèi)的一般用的不多,當然還是要視具體情況而定。在
Charater Devices: 字符設備支持,把Virtual terminal,support console on virtual terminal, Standard/generitic serial support和Support for console on serial port這兩項編譯進(jìn)內核就差不多了。
File Systems: 文件系統支持,由于我們使用的ext2文件系統,所以把Second extended fs support 這一項編譯進(jìn)內核。另外/proc文件系統也編譯進(jìn)內核,因為proc文件系統很有用。其余的ext3,fat,Vfat,ntfs 給M上吧,另外吧網(wǎng)絡(luò )文件系統nfs也M上吧,Partion types這里面的選擇PC BIOS就可以了,Native Language Support把codepage 437,936以及nls iso8859-1編譯進(jìn)內核,其它的就不用選了。
USB Support: Usb設備支持,把UHCI和OHCI support給M上,另外USB Mass Storage Suppor 一定要選上,把它編譯進(jìn)內核或者M上都可以。最后吧USB Device filesystems 給編譯進(jìn)內核,這會(huì )在/proc文件系統里面生成相應的選項,便于調試用。其它的聲卡,紅外線(xiàn)之類(lèi)的設備都可以不選。
這里沒(méi)有涉及的選項都是不常用的。
內核配置完畢,保存退出。
4.3. 建立依賴(lài)關(guān)系
這一步一個(gè)命令make dep就可以搞定。內核源碼樹(shù)中大多數文件都會(huì )與一些頭文件有依賴(lài)關(guān)系,make dep期間會(huì )在內核源碼樹(shù)中每個(gè)子目錄下面產(chǎn)生一個(gè)隱藏的.depend文件。此文件內包含子目錄里面各文件所依賴(lài)的頭文件清單。
4.4. 建立內核
make bzImage or make zImage
注意bzImage和在zImage都是經(jīng)gzip算法壓縮過(guò)的內核映像,所不同的是在zImage的大小無(wú)法超過(guò)500KB,而bzImage則沒(méi)有這個(gè)限制,如果映象建立過(guò)程中有錯誤,一個(gè)就是你的內核配置不正確,還有一個(gè)可能就是需要make mrproper來(lái)消除上一次的編譯記錄,make mrproper之后內核源碼相當于剛安裝時(shí)候的狀態(tài)。
4.5. 建立和安裝模塊
make modules & make modules_install
注意模塊的默認安裝位置是/lib/modules目錄下,目錄名即是你的內核版號,如果/lib/modules目錄下有一個(gè)相同的內核版本號目錄,如果很重要的話(huà)你最好把它備份,因為會(huì )被新的覆蓋。至此內核以及相應的模塊已經(jīng)建立好了。
5.建立根文件系統
5.1.根文件系統的基本結構
首先建立一個(gè)roofs文件夾用來(lái)存放根文件系統的內容。
#mkdir /mnt/rootfs
根文件系統的頂層目錄: (摘自<<構建嵌入式LINUX系統>> page 179)
|
目錄 |
內容 |
|
bin |
必要的用戶(hù)命令(二進(jìn)制文件) |
|
boot |
引導加載程序使用的靜態(tài)文件 |
|
dev |
設備文件和其它特殊文件 |
|
etc |
系統配置文件,包括啟動(dòng)文件 |
|
home |
用戶(hù)主目錄 |
|
lib |
必要的連接庫,例如C連接庫,內核模塊 |
|
mnt |
安裝點(diǎn),用于暫時(shí)安裝文件系統 |
|
opt |
附加的軟件套件 |
|
proc |
用來(lái)提供內核與進(jìn)程信息的虛擬文件系統 |
|
root |
root用戶(hù)的主目錄 |
|
sbin |
必要的系統管理員命令(二進(jìn)制文件 ) |
|
tmp |
暫時(shí)性的文件 |
|
usr |
在第二層包括對大多數用戶(hù)都有用的大量應用程序和文件(包括庫文件) |
|
var |
監控程序和工具程序所存放的可變數據 |
5.2. 建立UsbLinux根文件系統的基本結構
對于u盤(pán)上的linux或者做網(wǎng)關(guān)的linux來(lái)說(shuō),用戶(hù)的權限問(wèn)題并不復雜,我們只需要設置一個(gè)超級用戶(hù)以及其它系統服務(wù)必要的帳戶(hù)即可(比如ftp,sshd等等),由于相當于是單用戶(hù),因此home目錄也可以不要,其它的目錄在我看來(lái)都是必要的,下面我們開(kāi)始建立根文件系統的基本結構。
#cd /mnt/rootfs
#mkdir bin sbin dev etc lib root tmp usr var proc opt mnt
#mkdir usr/{bin,sbin ,lib,share}
#mkdir var/{lock,log,run,empty}
一般二進(jìn)制命令可以存放的目錄包括bin,sbin,usr/bin,usr/sbin,它們有什么區別呢?
二進(jìn)制文件放在哪個(gè)目錄,這與它在系統中所扮演的角色密切相關(guān),如果這是普通用戶(hù)和系統管理員必備的二進(jìn)制文件(比如ls和mkdir等),就會(huì )放在bin目錄下,如果只是系統管理員所具有的一些特權指令(普通用戶(hù)使用這些指令有限制,如ifconfig),那么它應該放在sbin目錄下,usr/bin目錄下存放的是普通用戶(hù)和管理員"不常用"的命令,而usr/sbin目錄下是管理員"不常用"的命令。
上面已經(jīng)說(shuō)過(guò)我們不需要區分普通用戶(hù)和系統管理員(root),因此我們只需創(chuàng )建一個(gè)系統管理員賬號就可以了,但是這里為什么我們還要創(chuàng )建這四個(gè)目錄呢? 是因為我們用到busybox套件,下面說(shuō)明安裝定制應用程序的時(shí)候會(huì )講到。
下面我們把剛才建立的內核模塊拷貝到lib目錄下(注:以后我們所有的操作都是以/mnt/rootfs為根操作的)
#mkdir lib/modules
#cp –dpR /lib/modules/
5.3. 選擇鏈接庫
鏈接庫是文件系統中一個(gè)非常重要的部分, 它也是整個(gè)根文件系統中最耗空間的一個(gè)部分。鏈接庫是應用程序執行期間必不可少的一部分,當然如果你編譯應用程序的時(shí)候庫都是靜態(tài)編譯進(jìn)去的,那么就不需要額外麻煩的自己建立鏈接庫了,比如嵌入式系統中的uClinux,不過(guò)這個(gè)做法的缺點(diǎn)就是會(huì )額外的消耗存儲空間。我們這里采用動(dòng)態(tài)鏈接的方法。目前比較流行的鏈接庫有glibc和uClibc,glibc是gnu的C鏈接庫,一般的linux發(fā)型版都是使用的glibc庫,而uClibc主要是針對嵌入式系統而定制的庫,它的特點(diǎn)就是小。盡管uClibc也可以用在X86機器上,但它并不具有glibc的穩定性,一般在pc機上都是使用的glibc庫。我們的目標機是pc機,所以我們選擇glibc庫,我們可以直接把宿主機上面的庫文件拿來(lái)用。
5.4 建立設備文件
依照unix的傳統,在Linux系統中任何對象(包括設備 )都可以視為文件,在Linux系統中所有的設備文件都放在dev目錄下面,建立設備文件通常有兩種方法,一個(gè)是直接把宿主機上面的拷貝過(guò)來(lái)(拷貝的時(shí)候需要加上dpR參數),另外一種方法就是自己手工用mknod創(chuàng )建(注意這兩種方法都需要root權限)。
一般情況下我們都是使用第一種方法,但是這里面為了便于大家更深入的理解設備文件,我使用第二種方法來(lái)創(chuàng )建。首先來(lái)看如何使用mknod命令來(lái)創(chuàng )建特定的設備文件。
#cd dev
#mknod -m 666 null c 1 3
上面這條命令創(chuàng )建了null設備,-m 參數指定所創(chuàng )建設備的基本權限,null是設備名稱(chēng),c代表是字符設備,相應的塊設備用b表示,1是主編號,3是次編號。
關(guān)于設備的主次編號的權威信息的來(lái)源可以查看內核源碼樹(shù)中的
Documentation/devices.txt
我們這里需要建立的dev條目如表格所示。
|
文件名 |
說(shuō)明 |
類(lèi)型 |
主編號 |
次編號 |
權限位 |
|
mem |
物理內存存取 |
字符設備 |
1 |
1 |
600 |
|
console |
系統控制臺 |
字符設備 |
5 |
1 |
600 |
|
urandom |
真隨機數產(chǎn)生器 |
字符設備 |
1 |
8 |
644 |
|
null |
null(黑洞)設備 |
字符設備 |
1 |
3 |
666 |
|
zero |
以null byte(零值字節)為數據來(lái)源 |
字符設備 |
1 |
5 |
666 |
|
tty |
現行的tty設備 |
字符設備 |
5 |
0 |
666 |
|
tty0 |
現行的虛擬控制臺 |
字符設備 |
4 |
0 |
600 |
|
tty1 |
第一個(gè)虛擬控制臺 |
字符設備 |
4 |
1 |
600 |
|
ptyp0 |
first pseudo-tty master |
字符設備 |
2 |
0 |
666 |
|
ttyp0 |
first BSD pseudo-tty slave |
字符設備 |
3 |
0 |
666 |
|
ram0 |
第一塊 ram盤(pán) |
塊設備 |
1 |
0 |
640 |
|
hda |
主IDE硬盤(pán)(或者光盤(pán)) |
塊設備 |
3 |
0 |
660 |
|
hda1 |
上述主盤(pán)的第一個(gè)分區 |
塊設備 |
3 |
1 |
660 |
|
hdb |
從IDE硬盤(pán)(或者光盤(pán)) |
塊設備 |
3 |
64 |
660 |
|
hdb1 |
上述從盤(pán)的第一個(gè)分區 |
塊設備 |
3 |
65 |
660 |
|
sda |
第一塊scsi盤(pán)的整個(gè)盤(pán) |
塊設備 |
8 |
0 |
660 |
|
sda1 |
第一塊scsi盤(pán)的第一個(gè)分區 |
塊設備 |
8 |
1 |
660 |
|
sdb |
第二塊scsi盤(pán)的整個(gè)盤(pán) |
塊設備 |
8 |
16 |
660 |
|
sdb1 |
第二塊scsi盤(pán)的第一個(gè)分區 |
塊設備 |
8 |
16 |
660 |
|
fd0 |
第一個(gè)軟盤(pán)設備 |
塊設備 |
2 |
0 |
660 |
下面我們寫(xiě)一個(gè)sh腳本mkdev.sh來(lái)創(chuàng )建這些設備,腳本內容如下:
#!/bin/sh
rm -rf mem console urandom null zero tty* ptyp* ram* hda* hdb* \
sda* sdb* fd* hdc cdrom
mknod -m 600 mem c 1 1
mknod -m 600 console c 5 1
mknod -m 644 urandom c 1 8
mknod -m 666 null c 1 3
mknod -m 666 zero c 1 5
mknod -m 666 tty c 5 0
for i in 0 1 2 3 4
do
mknod -m 600 tty$i c 4 $i
mknod -m 660 ttyp$i c 3 $i
done
for i in 0 1 2 3 4
do
mknod -m 660 ptyp$i c 2 $i
done
mknod -m 640 ram0 b 1 0
mknod -m 640 ram1 b 1 1
mknod -m 660 hda b 3 0
mknod -m 660 hdb b 3 64
mknod -m 660 hdc b 22 0
ln -s hdc cdrom
for i in 1 2 3 4 5 6 7 8 9 10
do
mknod -m 660 hda$i b 3 $i
mknod -m 660 hdbd$i b 3 `expr 64 + $i`
done
mknod -m 660 sda b 8 0
mknod -m 660 sdb b 8 16
for i in 1 2 3 4 5
do
mknod -m 660 sda$i b 8 $i
mknod -m 660 sdb$i b 8 `expr 16 + $i`
done
mknod -m 640 fd0 b 2 0
#end
#./mkdev.sh
5.5. 定制應用程序。
這個(gè)是個(gè)大頭,但是由于一般的發(fā)行版自帶的應用程序都很龐大,而且應用程序依賴(lài)的動(dòng)態(tài)鏈接庫也大的出奇,所以就有人想出很多辦法,其中busybox在這方面做的非常的好,目前busybox在嵌入式方面應用非常廣泛,BusyBox真如其名,它把所有的應用程序集成在一個(gè)命令里面,目前BusyBox支持unix/linux命令集里面的大部分命令,包括基本的命令cp,cd,chmod,chown,date,cat,ar等,編輯工具vi,awk等,網(wǎng)絡(luò )工具ifconfig,netstat,route,telnet,ftpget,ftpput,telnetd等,模塊工具lsmod,insmod,rmmod,modprobe,壓縮解壓縮工具gzip,gunzip,tar,bzip,bunzip,zip,unzip等,查找工具find,grep,xargs,init工具init,poweroff,halt,reboot,賬號密碼管理工具addgroup,delgroup,adduser,deluser,getty,login,shadow,進(jìn)程相關(guān)工具free,kill,killall,top,ps等,其它的last,fdisk,dmesg,swapon,swapoff等等都有,另外,BusyBox還提供幾個(gè)shell,我們一般用ash,它和bash非常的相似。
下面說(shuō)說(shuō)如何使用busybox定制自己的應用程序。
首先到網(wǎng)上下載一個(gè)穩定的BusyBox版本,我用的版本是busybox-
#make menuconfig (不知道的選項看看help就可以了)
#make
#make install
注意busybox默認是安裝到根目錄下的_install文件文件夾。
#cd _install
#ls
你會(huì )發(fā)現bin目錄下只有一個(gè)busybox二進(jìn)制文件,其它的命令,bin,sbin以及
usr/bin,usr/sbin目錄下的都是指向busybox的鏈接文件。牛逼吧,這么多命令一個(gè)應用程序就搞定了,我們看看busybox有多大
#du -k bin/busybox
420
這是我定制出來(lái)的busybox的大小,夠小的吧。
在busybox的根目錄下編譯好二進(jìn)制程序之后。
#make install PREFIX=/mnt/roofs
這樣,應用程序就會(huì )安裝到指定位置,切換到/mnt/rootfs下看看,bin目錄,sbin目錄,usr/bin目錄,usr/sbin目錄下是不是出現了很多的應用程序。
busybox安裝好之后,看看它依賴(lài)的動(dòng)態(tài)鏈接庫
#ldd busybox
libm.so.6 => /lib/tls/libm.so.6 (0×40026000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0×40048000)
libc.so.6 => /lib/tls/libc.so.6 (0×42000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
#cd /mnt/rootfs
#cd lib
#cp -dpR /lib/libc-
#cp -dpR /lib/libc.so.6 ./
#cp -dpR /lib/libm* ./
#cp -dpR /lib/libcrypt-
#cp -dpR /lib/libcrypt.so.1 ./
#mkdir tls
#ln -s libc-
#ln -s libm-
除了基本的命令之外,BusyBox還支持init功能,如同其它的init一樣,busybox的init也是完成系統的初始化工作,關(guān)機前的工作等等,我們知道在Linux的內核被載入之后,機器就把控制權轉交給內核,linux的內核啟動(dòng)之后,做了一些工作,然后找到根文件系統里面的init程序,并執行它,BusyBox的init進(jìn)程會(huì )依次進(jìn)行以下工作:(參考<<構建嵌入式LINUX系統>> p201)
1. 為init設置信號處理過(guò)程
2. 初始化控制臺
3. 剖析/etc/inittab文件
4. 執行系統初始化命令行,缺省情況下會(huì )使用/etc/init.d/rcS
5. 執行所有導致init暫停的inittab命令(動(dòng)作類(lèi)型:wait)
6. 執行所有僅執行一次的inittab(動(dòng)作類(lèi)型:once)
一旦完成以上工作,init進(jìn)程便會(huì )循環(huán)執行以下進(jìn)程:
1. 執行所有終止時(shí)必須重新啟動(dòng)的inittab命令(動(dòng)作類(lèi)型:once)
2. 執行所有終止時(shí)必須重新啟動(dòng)但啟動(dòng)前必須詢(xún)問(wèn)用戶(hù)的inittab命令(動(dòng)作類(lèi)型:askfirst)
初始化控制臺之后,BusyBox會(huì )檢查/etc/inittab文件是否存在,如果此文件不存在,BusyBox會(huì )使用缺省的inittab配置,它主要為系統重引導,系統掛起以及init重啟動(dòng)設置缺省的動(dòng)作,此外它還會(huì )為四個(gè)虛擬控制臺(tty1到tty4)設置啟動(dòng)shell的動(dòng)作。如果未建立這些設備文件,BusyBox會(huì )報錯。
inittab文件中每一行的格式如下所示:(busybox的根目錄下的example文件夾下有詳盡的inittab文件范例)
id:runlevel:action:process
盡管此格式與傳統的Sytem V init類(lèi)似,但是,id在BusyBox的init中具有不同的意義。對BusyBox而言,id用來(lái)指定啟動(dòng)進(jìn)程的控制tty。如果所啟動(dòng)的進(jìn)程并不是可以交互的shell,例如BusyBox的sh(ash),應該會(huì )有個(gè)控制tty,如果控制tty不存在,Busybox的sh會(huì )報錯。BusyBox將會(huì )完全忽略runlevel字段,所以空著(zhù)它就行了,你也許會(huì )問(wèn)既然沒(méi)用保留著(zhù)它干嗎,我想大概是為了和傳統的Sytem V init保持一致的格式吧。process字段用來(lái)指定所執行程式的路徑,包括命令行選項。action字段用來(lái)指定下面表中8個(gè)可應用到process的動(dòng)作之一。
|
動(dòng)作 |
結果 |
|
sysinit |
為init提供初始化命令行的路徑 |
|
respawn |
每當相應的進(jìn)程終止執行便會(huì )重新啟動(dòng) |
|
askfirst |
類(lèi)似respawn,不過(guò)它的主要用途是減少系統上執行的終端應用程序的數量。它將會(huì )促使init在控制臺上顯示“Please press Enter to active this console”的信息,并在重新啟動(dòng)之前等待用戶(hù)按下enter鍵 |
|
wait |
告訴init必須等到相應的進(jìn)程完成之后才能繼續執行 |
|
once |
僅執行相應的進(jìn)程一次,而且不會(huì )等待它完成 |
|
ctratldel |
當按下Ctrl+Alt+Delete組合鍵時(shí),執行相應的進(jìn)程 |
|
shutdown |
當系統關(guān)機時(shí),執行相應的進(jìn)程 |
|
restart |
當init重新啟動(dòng)時(shí),執行相應的進(jìn)程,通常此處所執行的進(jìn)程就是init本身 |
以下是我的usblinux的inittab文件
::sysinit:/etc/init.d/rcS
::respawn:/sbin/getty 38400 tty1
tty2::askfirst:-/bin/sh
tty3::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/bin/umount -a -r
這個(gè)inittab執行下列動(dòng)作
1. 將/etc/init.d/rcS設置成系統的初始化文件
2. 在38400 bps的虛擬終端tty1上啟動(dòng)一個(gè)登陸會(huì )話(huà) (注意getty的用法)
3. 在虛擬終端tty2和tty3上啟動(dòng)askfirst動(dòng)作的shell
4. 如果init重新啟動(dòng),將/sbin/init設置成它會(huì )執行的程序
5. 告訴init,在系統關(guān)機的時(shí)候執行umount命令卸載所有文件系統,并且在卸載失敗時(shí)用只讀模式?jīng)_新安裝以保護文件系統。
5.6 系統的配置文件
配置文件一般放在/etc/目錄下,
#!/bin/sh
/bin/mount -n -t proc /proc /proc
/bin/mount -n -o remount,rw /
/bin/mount -av
/bin/hostname usblinux
/etc/init.d/rc.nic
/etc/init.d/rc.network
/etc/init.d/rc.usb
/etc/init.d/rc.local
1. 安裝proc文件系統,但是不寫(xiě)入/etc/mtab文件(mtab文件是df命令讀取的文件)
2. 以讀寫(xiě)模式重新掛載根文件系統(需要/etc/fstab文件)
3. mount -av 掛載所有在/etc/fstab里面列出的文件系統
4. 主機名命名為usblinux
5. 依次執行rc.nic(自動(dòng)檢測網(wǎng)卡),rc.network(配置網(wǎng)絡(luò )),rc.usb(加載usb模塊),rc.local(執行本地的一些服務(wù))
上面使用mount命令的時(shí)候已經(jīng)涉及到了fstab文件,下面是我的fstab文件
/dev/ram0 / ext2 defaults 0 0
proc /proc proc defaults 0 0
關(guān)于fstab配置文件的語(yǔ)法可以man fstab
其實(shí)rcS里面的mount -av沒(méi)有必要加上去。
這個(gè)文件里面的內容是動(dòng)態(tài)變化的,當mount一個(gè)文件系統的時(shí)候,如果mount 沒(méi)有加上-n參數,那么安裝信息就會(huì )寫(xiě)入mtab文件,df命令讀取的就是這個(gè)文件。
這個(gè)文件是sh用的,當用戶(hù)獲得一個(gè)shell后,sh就會(huì )根據這個(gè)文件配置用戶(hù)的登陸環(huán)境,下面是我的profile文件。
PATH=/bin:/sbin:/usr/bin:/usr/sbin
PS1=’[\u@\h \W]\$ ‘
HOSTNAME=’/bin/hostname’
export PATH HOSTNAME PS1
alias l.=’ls -d .[a-zA-Z]* –color=tty’
alias rm=’rm -i’
alias cp=’cp -i’
alias mv=’mv -i’
export PATH=/usr/local/bin:$PATH
export PATH=/usr/local/sbin:$PATH
其中PATH環(huán)境變量指定當用戶(hù)鍵入一個(gè)命令時(shí),sh尋找這個(gè)命令的路徑。
PS1指定sh提示符的格式
其它的export命令,alias命令不用說(shuō)了吧,busybox里面的ash和bash非常相似,因此只要熟悉bash就會(huì )不成問(wèn)題。
這兩個(gè)文件是與lib庫有關(guān)的,它們用來(lái)指定應用程序尋找lib庫的路徑。
我的ld.so.conf文件內容如下。
/lib
/usr/lib
/usr/local/lib
ld.so.cache里面的內容是由是ldconfig命令生成的,ldconfig根據ld.so.conf配置文件生成ld.so.cache里面的內容,應用程序讀取的是ld.so.cache文件,因此如果變動(dòng)了ld.so.conf文件,需要運行一次ldconfig才能是新的配置生效,另外如果新加了lib庫文件,也需要ldconfig。
group里面存放的是用戶(hù)組的信息。
我的group文件內容如下:
root:x:0:root
ftp:x:50:
passwd里面存放的是用戶(hù)的信息
我的passwd文件內容如下:
root:x:0:0:root:/root:/bin/sh
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
sshd:x:74:74:piviledge-separated SSH:/var/empty/sshd:/sbin/nologin
注意,group和passwd里面的每一行都不是多余的。
shadow文件是pam認證用到的密碼存放文件
網(wǎng)絡(luò )應用程序用到的標準服務(wù)端口映射表
我的services文件如下:
tcpmux 1/tcp
tcpmux 1/udp
ftp-data 20/tcp
ftp 21/tcp
ssh 22/tcp
ssh 22/udp
telnet 23/tcp
nameserver 42/tcp name
syslog 514/udp
auth 113/tcp authentication tap ident
因為我需要開(kāi)啟sshd,syslogd服務(wù),同時(shí)會(huì )使用ftp,ssh,telnet應用程序。所以就會(huì )加上上面的東西,但是注意并不是所有的網(wǎng)絡(luò )應用程序都會(huì )依賴(lài)與services文件,比如telnet,但是也許telnetd需要。
這個(gè)文件的作用很大,沒(méi)有它很多程序都不能正常運行,關(guān)于它的具體作用還是用man nsswitch.conf看看吧。
我的nsswitch.conf文件內容如下:
passwd: files
shadow: files
group: files
hosts: files dns
ethers: files
netmasks: files
networks: files
protocols: files
services: files
netgroup: files
publickey: files
automount: files
aliases: files
注意hosts這一行一定要加上dns,不然即使有resolv.conf文件,域名也不能解析,注意nsswitch.conf是對應一組lib庫的,這里我們用了files,dns,因此需要拷貝相應的lib庫到/lib目錄下.
#cd /mnt/rootfs
#cp -dpR /lib/libnss_files* ./lib
#cp -dpR /lib/libnss_dns* ./lib
我的hosts文件內容如下,不用說(shuō)也應該清楚什么意思了,不清楚的man hosts
127.0.0.1 localhost:localdomain localhost
host.conf和resolv.conf是域名解析的時(shí)候用到的配置文件,其中resolv.conf里面是域名服務(wù)器的ip地址,host.conf里面放的是主機的查找規則。不了解的還是man host.conf和man resolv.conf
我的host.conf與resolv.conf文件內容分別如下:
#cat /mnt/rootfs/etc/host.conf
order hosts,bind
#cat /mnt/rootfs/etc/resolv.conf
nameserver 202.112.20.131
syslogd服務(wù)程序讀取的配置文件。
我的文件內容如下:
# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.* /dev/console
# Log anything (except mail) of level info or higher.
# Don’t log private authentication messages!
*.info;mail.none;authpriv.none;cron.none /var/log/messages
# The authpriv file has restricted access.
authpriv.* /var/log/secure
# Save boot messages also to boot.log
local7.* /var/log/boot.log
5.7 系統初始化的腳本
上面說(shuō)到rcS文件時(shí),涉及到了/etc/init.d/rc.nic,/etc/init.d/rc.network,/etc/init.d/rc.usb,/etc/init.d/rc.local四個(gè)初始化腳本文件。下面來(lái)說(shuō)說(shuō)它們的作用。
此文件用來(lái)自動(dòng)加載網(wǎng)卡對應的模塊(驅動(dòng)),并且刪除沒(méi)有用到的網(wǎng)卡驅動(dòng)模塊。
#!/bin/sh
#
# detect network cards shell
#
dmesg -n 1 #prevent the messages from appearing on the console
ERR_DEV=/dev/null # redirect verbose messages
NetcardPath=/lib/modules/
loaded=4 #the kernel already detected card,you may want to change it
#according to file `/proc/net/dev`
# invoked by the init script or by the user?
[ "`basename $0`" = "rc.nic" ] && MODE=init || MODE=user
# number of NICs already detected
NICs=$((`cat /proc/net/dev | wc -l` -$loaded))
# when init, skip auto probing if we already found some NIC(s)
if [ $NICs -ge 1 -a "$MODE" = "init" ]; then
echo "Found $NICs network card(s). Skip auto probing …"
exit 0
fi
# official NIC modules
NET_MODs=`find /lib/modules/\`uname -r\`/kernel/drivers/net/ \
-type f -printf "%f\n" 2>$ERR_DEV \
| cut -d "." -f1`
# save the original dmesg messages first
[ -e /var/log/dmesg ] || dmesg > /var/log/dmesg
echo "Probing network cards … "
CUR_NICs=$NICs
for i in $NET_MODs ; do
ORG_MODs=`cat /proc/modules | wc -l`
ORG_NICs=$CUR_NICs
echo -en "\r\t$i \t"
#if modprobe fail we think that this module is not needed
#so we delete it to save the space
if ! modprobe $i 1>$ERR_DEV 2>$ERR_DEV
then
temp=`find $NetcardPath -name $i.o`
if [ -f $temp ]
then
rm -rf $temp
fi
fi
CUR_MODs=`cat /proc/modules | wc -l`
CUR_NICs=$((`cat /proc/net/dev | wc -l` -$loaded))
if [ $CUR_NICs -eq $ORG_NICs ]; then
if [ $CUR_MODs -gt $ORG_MODs ]; then #it is not a netcard module
#so we delete it
RMMODs=`head -$(($CUR_MODs-$ORG_MODs)) /proc/modules | cut -d" " -f1`
for m in $RMMODs ; do
rmmod $m 1>$ERR_DEV 2>$ERR_DEV
done
fi
else
echo " ($(($CUR_NICs-$ORG_NICs)))"
fi
done
echo -e "\r \rFound $(($CUR_NICs-$NICs)) card(s), done."
rmmod -as
exit $(($CUR_NICs-$NICs))
看懂這個(gè)腳本就需要你熟悉shell編程了。由于比較大,我這里不作解釋。
這個(gè)腳本的內容大部分是從cdlinux上面copy過(guò)來(lái)的,但是對其進(jìn)行了修改,其中最大的修改就是添加了刪除沒(méi)有用到的模塊的功能,這主要是為了節省空間所用。
這個(gè)腳本主要是初始化網(wǎng)絡(luò )配置,
#!/bin/sh
#/sbin/ifconfig eth1 218.199.20.98 up
/sbin/ifconfig eth0 192.168.0.3 up
/sbin/ifconfig lo 127.0.0.1 up
route add default gw 192.168.0.1 dev eth0
這個(gè)腳本需要根據不同的環(huán)境進(jìn)行修改。接觸過(guò)linux的人相信這個(gè)不難看懂。
加載usb驅動(dòng)模塊,當然如果你的內核是靜態(tài)編譯進(jìn)usb模塊的,那就沒(méi)有必要在這里多此一舉了,不過(guò)如果我們要做個(gè)網(wǎng)關(guān)服務(wù)器,還是把它做成動(dòng)態(tài)的模塊比較好,因為網(wǎng)關(guān)服務(wù)器基本上不需要用到u盤(pán),我們大可刪除掉usb驅動(dòng)模塊,以節省空間。我們之所以需要usb的驅動(dòng)模塊,不要忘了我們的usbinux是放在u盤(pán)上面運行的。當然并不是說(shuō)要在u盤(pán)上面運行linux,一定需要內核支持usb才行,不管是硬盤(pán),u盤(pán),還是軟盤(pán)都只是個(gè)載體,第一章已經(jīng)說(shuō)了,我們的文件系統是在ramdisk中的,因此只要內核和文件系統被載入內存,我們就不再需要載體(存儲設備)。但是我們很多東西可以放在u盤(pán)上面,以節省ramdisk的存儲空間,所以還是需要內核識別u盤(pán),等系統啟動(dòng)之后再把需要的東西從u盤(pán)拷貝到ram里面。
rc.usb內容如下:
#!/bin/sh
## This script is to initilize usb controller and
## The driver module usb-storage
## To use usb under linux the module usbcore,scsi_mod
## and sd_mod are needed,in this
## system they are complied in kernel
#/sbin/usb is the small script to start or stop usb support
/sbin/usb start
#script rc.usb end
這個(gè)腳本里面用到了/sbin/usb這個(gè)程序,其實(shí)并不是一個(gè)真正的程序,它是我寫(xiě)的一個(gè)加載和卸載usb模塊的shell腳本。/sbin/usb腳本內容如下:
#!/bin/sh
#
#A simple startup script to start usb for linux
#
case "$1" in
start)
/sbin/modprobe usbcore
/sbin/modprobe usb-uhci
/sbin/modprobe usb-storage
;;
stop)
/sbin/rmmod usbcore
/sbin/rmmod usb-uhci
/sbin/rmmod usb-storage
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
#script /sbin/usb end
我之所以寫(xiě)了這個(gè)usb腳本,是因為我發(fā)現,啟動(dòng)usblinux后,當機子用過(guò)一個(gè)u盤(pán)時(shí),即使這個(gè)u盤(pán)umount掉了,再使用另外一個(gè)u盤(pán)的時(shí)候就會(huì )出現問(wèn)題。也許是我的哪邊配置有誤,不過(guò)不管怎么說(shuō),這個(gè)腳本還是有用的。
注意:雖然上面只列出了,usbcore,usb-uhci,usb-storage三個(gè)模塊,要能夠成功掛載u盤(pán),還需要scsi的支持,也就是需要scsi_mod.o sd_mode.o兩個(gè)模塊,我的內核是把這兩個(gè)模塊靜態(tài)編譯進(jìn)內核的,因此也就不需要再手動(dòng)加載了。我之所以把對scsi支持的功能靜態(tài)編譯進(jìn)內核,是為了測試方便的原故,我測試工具使用的是vmware虛擬機,因為vmware基本上使用scsi硬盤(pán),為了避免添加linuxrc文件,我把vmware的硬盤(pán)驅動(dòng)BusLogic.o靜態(tài)編譯進(jìn)了內核,所以上面的scsi的兩個(gè)模塊也要編譯進(jìn)內核。
這個(gè)shell腳本沒(méi)有什么好說(shuō)的,主要是初始化本地的一些服務(wù),比如sshd,syslogd等等
我的rc.local腳本內容如下:
#!/bin/sh
#/sbin/sshd
/sbin/syslogd
在本地啟動(dòng)syslogd服務(wù)。
5.8 添加額外的應用程序
雖然busybox支持大多數應用程序,但是往往我們需要的程序它并不支持,這時(shí)候我們就只有copy我們的宿主機上的了,第一章說(shuō)了,我們的usblinux需要能夠fdisk存儲設備,能夠mkfs文件系統,能夠使用grub安裝grub到指定存儲設備。busybox有fdisk,但是mkfs.*在我使用的busybox版本里面還不支持,另外ldconfig這個(gè)必須的應用程序busybox里面好像也沒(méi)有。另外我們也許想在usblinux里面臨時(shí)使用一下ftp服務(wù)器,用來(lái)傳輸文件用,調試的時(shí)候strace是必不可少的工具,加進(jìn)硬盤(pán)檢測工具smartmontools也是不錯的主意,充當網(wǎng)關(guān)服務(wù)器sshd必不可少吧,雖然可以用其它的比如telnetd等代替,但是它們并沒(méi)有sshd來(lái)的安全,因此我還是選擇了sshd。
上面說(shuō)了這么多的應用程序,如果不采取任何措施直接copy到rootfs里面的話(huà),可想而知,根文件系統的大小會(huì )相當大,sshd一個(gè)就會(huì )凈增文件系統
有些應用程序譬如sshd,mkfs*,grub,strace等等,我們平時(shí)很少用到,因此如果我們能想出一個(gè)辦法需要這個(gè)應用程序的時(shí)候調度出來(lái),不需要的時(shí)候把它刪掉,那就解決了問(wèn)題。方法也許有很多,我使用的方法是把這些應用程序及其依賴(lài)的庫文件壓縮,然后把它們的壓縮文件安裝到opt目錄下,需要的時(shí)候解壓就行了,不需要的時(shí)候把解壓出來(lái)的文件刪除掉。我opt目錄文件內容如下:
#ls opt
ldconfig.tar.gz rz.tar.gz strace.tar.gz
grub.tar.gz mkfs.tar.gz smartmontools.tar.gz
iptables.tar.gz pureftpd.tar.gz sshd.tar.gz
我之所以把ldconfig壓縮,是因為ldconfig有536k之大,rz是學(xué)校校園上網(wǎng)認證的一個(gè)程序,strace是個(gè)調試程序,grub,mkfs不用說(shuō)了吧,smartmontools是硬盤(pán)壞道檢測工具,iptables做網(wǎng)關(guān)服務(wù)器所必須的,pureftpd一個(gè)很方便的ftp服務(wù)器程序,sshd遠程登陸工具,包括服務(wù)端和客戶(hù)端的。
下面使用兩個(gè)腳本來(lái)調入和調出/opt下的指定應用程序。
1. 調入腳本expand
#!/bin/sh
TOOL=$1
if [ ! -f /opt/$TOOL.tar.gz ]
then
echo "No such tool!"
exit
fi
mkdir /tmp/tool
cp /opt/$TOOL.tar.gz /tmp/tool
cd /tmp/tool
tar zxf $TOOL.tar.gz
rm -rf $TOOL.tar.gz
cp -dpR /tmp/tool/$TOOL/etc/* /usr/local/etc 2>/dev/null
cp -dpR /tmp/tool/$TOOL/sbin/* /usr/local/sbin 2>/dev/null
cp -dpR /tmp/tool/$TOOL/bin/* /usr/local/bin 2>/dev/null
cp -dpR /tmp/tool/$TOOL/lib/* /usr/local/lib 2>/dev/null
rm -rf /tmp/tool
echo "done"
2. 調出腳本/sbin/depand
#!/bin/sh
path=/usr/local
case $
"ldconfig")
rm -rf $path/sbin/ldconfig
echo "done";;
"grub")
rm -rf $path/sbin/grub
echo "done";;
"smartmontools")
rm -rf $path/sbin/smartctl
echo "done";;
"strace")
rm -rf $path/bin/strace
echo "done";;
"rz")
rm -rf $path/bin/rz
rm -rf $path/etc/rz.conf
rm -rf $path/lib/libpcap*
echo "done";;
"mkfs")
rm -rf $path/sbin/mkfs*
rm -rf $path/lib/libext2*
rm -rf $path/lib/libe2p*
rm -rf $path/lib/libcom_err*
rm -rf $path/lib/libuuid*
echo "done";;
"pureftpd")
rm -rf $path/sbin/*pure*
echo "done";;
*)
echo "this tool is not installed!"
esac
譬如要調入grub這個(gè)工具,只需要在命令行敲入expand grub即可,使用完grub之后,只要depand grub就可釋放grub占有的ram空間。
(注意:expand和depand并不適用與iptables與sshd這兩個(gè)應用程序,對它們我們需要額外編寫(xiě)腳本,因此expand應該加上對這兩個(gè)程序的拒絕執行動(dòng)作,但是我這里沒(méi)有加,為了安全起見(jiàn),建議還是應該加上)
opt目錄下的壓縮文件并不是隨便做的,我們必須遵循一定的規范,下面我們以制作mkfs工具來(lái)說(shuō)明制作過(guò)程。
#cd /mnt/rootfs/opt
#mkdir mkfs
#cd mkfs
#mkdir bin sbin etc lib
#cp -dpR /lib/libext2fs.so.2* ./lib
#cp -dpR /lib/libe2p.so.2* ./lib
#cp -dpR /lib/libuuid.so.1* ./lib
#cp -dpR /lib/libcom_err.so.2* ./lib
#cp -dpR /sbin/mkfs* ./sbin
#cd ..
#tar zcf mkfs.tar.gz mkfs
#rm -rf mkfs
至此一個(gè)mkfs的壓縮文件mkfs.tar.gz就做好了。
通過(guò)這個(gè)過(guò)程再配備上面的expand腳本你應該知道制作的規則了吧。
下面用目錄樹(shù)了來(lái)表示這個(gè)架構:
bin sbin lib etc
sshd以及ssh這兩個(gè)程序依賴(lài)的庫文件比較多,而且涉及的其它文件也比較多。然而它卻是網(wǎng)關(guān)服務(wù)器所必不可少的。
要正確運行sshd要做以下幾件事情
1. 安裝sshd所依賴(lài)的庫文件
2. 安裝/lib/security目錄
3. 安裝/etc/pam.d文件夾
4. 安裝/etc/ssh文件夾
5. 創(chuàng )建sshd賬號
6. 創(chuàng )建/var/empty/sshd目錄
下面是整個(gè)流程
#cd opt
#mkdir sshd
#cd sshd
#mkdir bin etc lib
#cp /usr/bin/ssh bin
#cp /usr/sbin/sshd bin
#ldd /usr/sbin/sshd
libwrap.so.0 => /usr/lib/libwrap.so.0 (0×40026000)
libpam.so.0 => /lib/libpam.so.0 (0x
libdl.so.2 => /lib/libdl.so.2 (0×40037000)
libresolv.so.2 => /lib/libresolv.so.2 (0x
libutil.so.1 => /lib/libutil.so.1 (0x
libz.so.1 => /usr/lib/libz.so.1 (0x
libnsl.so.1 => /lib/libnsl.so.1 (0×4005e000)
libcrypto.so.4 => /lib/libcrypto.so.4 (0×40073000)
libkrb5.so.3 => /usr/kerberos/lib/libkrb5.so.3 (0×40164000)
libk5crypto.so.3 => /usr/kerberos/lib/libk5crypto.so.3 (0x
libcom_err.so.3 => /usr/kerberos/lib/libcom_err.so.3 (0×401d2000)
libc.so.6 => /lib/tls/libc.so.6 (0×42000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
libgssapi_krb5.so.2 => /usr/kerberos/lib/libgssapi_krb5.so.2 (0×401d5000)
(把這里面列出的庫文件拷貝到lib目錄下,注意拷貝的時(shí)候加上dpR參數,把原文件和鏈接文件全部拷貝過(guò)來(lái))
#cp -dpR /lib/security ./ (拷貝pam認證時(shí)需要的庫文件)
#cp -R /etc/ssh etc/ (拷貝ssh以及sshd的配置文件)
#mkdir etc/pam.d
#cp /etc/pam.d/system-auth etc/pam.d
#cp /etc/pam.d/sshd etc/pam.d
(把宿主機上的這兩個(gè)文件拷貝過(guò)來(lái),然后加以適當的修改,修改之后兩個(gè)文件內容如下)
#cat etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required /lib/security/pam_env.so
auth sufficient /lib/security/pam_unix.so likeauth nullok
auth required /lib/security/pam_deny.so
account required /lib/security/pam_unix.so
password required /lib/security/pam_cracklib.so retry=3 type=
password sufficient /lib/security/pam_unix.so nullok use_authtok md5 shadow
password required /lib/security/pam_deny.so
session required /lib/security/pam_limits.so
session required /lib/security/pam_unix.so
#cat etc/pam.d/sshd
#%PAM-1.0
#auth required /lib/security/pam_securetty.so
auth required /lib/security/pam_stack.so service=system-auth
auth required /lib/security/pam_nologin.so
account required /lib/security/pam_stack.so service=system-auth
password required /lib/security/pam_stack.so service=system-auth
session required /lib/security/pam_stack.so service=system-auth
session optional /lib/security/pam_console.so
(根據這兩個(gè)文件所用到的/lib/security目錄下的庫文件,對上面拷貝過(guò)來(lái)的庫文件做適當的裁減,下面是我裁減了的security下的庫文件列表)
#ls -l security
-rwxr-xr-x 1 root root 9684 12月 19 15:21 pam_access.so
-rwxr-xr-x 1 root root 47584 12月 19 15:21 pam_console.so
-rwxr-xr-x 1 root root 12936 12月 19 15:21 pam_cracklib.so
-rwxr-xr-x 1 root root 3404 12月 19 15:21 pam_deny.so
-rwxr-xr-x 1 root root 11592 12月 19 15:21 pam_env.so
-rwxr-xr-x 1 root root 8468 12月 19 15:21 pam_lastlog.so
-rwxr-xr-x 1 root root 12324 12月 19 15:21 pam_limits.so
-rwxr-xr-x 1 root root 4856 12月 19 15:21 pam_nologin.so
-rwxr-xr-x 1 root root 3708 12月 19 15:21 pam_permit.so
-rwxr-xr-x 1 root root 6544 12月 19 15:21 pam_securetty.so
-rwxr-xr-x 1 root root 11132 12月 19 15:21 pam_stack.so
lrwxrwxrwx 1 root root 11 12月 25 20:10 pam_unix_acct.so -> pam_unix.so
lrwxrwxrwx 1 root root 11 12月 25 20:10 pam_unix_auth.so -> pam_unix.so
lrwxrwxrwx 1 root root 11 12月 25 20:10 pam_unix_passwd.so -> pam_unix.so
lrwxrwxrwx 1 root root 11 12月 25 20:10 pam_unix_session.so -> pam_unix.so
-rwxr-xr-x 1 root root 48520 12月 19 15:21 pam_unix.so
(注意就是動(dòng)態(tài)鏈接庫,它也有一定的依賴(lài)關(guān)系,因此最好對lib/security目錄下的庫文件依次檢查其依賴(lài)關(guān)系,然后檢查/mnt/rootfs/opt/sshd/lib目錄下是否有其缺少的庫文件,如果缺少的需要拷貝相應的動(dòng)態(tài)鏈接庫到/mnt/rootfs/opt/sshd/lib目錄下.)
到這里,前4步已經(jīng)做完了,第5步已經(jīng)在前面的配置文件一節做完了。最后一步
#mkdir -p /mnt/rootfs/var/empty/sshd
下面我們把opt目錄下的sshd文件夾打包壓縮。
#cd /mnt/rootfs/opt/
#tar zcf sshd.tar.gz sshd
#rm -rf sshd
到這里sshd工具就做完了,下面我們寫(xiě)個(gè)shell腳本,來(lái)控制sshd的調入與調出
腳本放在/sbin目錄下,腳本文件名為ssh_sv,內容如下:
#!/bin/sh
case "$1" in
start)
ssh_sv stop
cd /tmp
tar zxf /opt/sshd.tar.gz
cd sshd
mv etc/* /etc
mv bin/ssh /usr/bin
mv bin/sshd /sbin/sshd
mv lib/* /usr/local/lib
mv security /lib
rm -rf /tmp/*
expand ldconfig
ldconfig
depand ldconfig
echo done;;
stop)
rm -rf /lib/security
rm -rf /etc/ssh
rm -rf /etc/pam.d
rm -rf /usr/bin/ssh
rm -rf /sbin/sshd
for i in libcom_err.so libcom_err.so.3 libcom_err.so.3.0 \
libcrack.so libcrack.so.2 libcrack.so.2.7 \
libcrypto.so.
libglib-1.2.so.
libgssapi_krb5.so libgssapi_krb5.so.2 libgssapi_krb5.so.2.2 \
libk5crypto.so libk5crypto.so.3 libk5crypto.so.3.0 \
libkrb5.so libkrb5.so.3 libkrb5.so.3.1 libnsl-
libnsl.so.1 libpam.so.0 libpam.so.0.75 libutil-
libutil.so libutil.so.1 libwrap.so libwrap.so.0 \
libwrap.so.
do
rm -rf /usr/local/lib/$i
done
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
我們只要使用ssh_sv start 便可調入sshd與ssh,使用ssh_sv stop便可以調出sshd與ssh。
iptables.tar.gz 是我們網(wǎng)關(guān)服務(wù)器最重要的一個(gè)壓縮包,我們的網(wǎng)關(guān)服務(wù)器的防火墻的配置,以及端口的映射等等都是通過(guò)iptables配置的。
#cd opt
#mkdir iptables
#cd iptables
#mkdir lib sbin etc
#cp -dpR /lib/iptables ./lib
#cp /sbin/iptables ./sbin
#touch etc/init.d/rc.firewall
rc.firewall為網(wǎng)關(guān)服務(wù)器的防火墻以及端口映射配置腳本。
我貼一個(gè)例子到這里,關(guān)于iptables的使用方法可參考相關(guān)文檔。
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ip_nat_ftp
/sbin/iptables -F INPUT
/sbin/iptables -F OUTPUT
/sbin/iptables -F FORWARD
/sbin/iptables -t nat -F POSTROUTING
/sbin/iptables -t nat -F PREROUTING
/sbin/iptables -t nat -A POSTROUTING -o eth1 -s 192.168.0.0/24 -j MASQUERADE
/sbin/iptables -t nat -A PREROUTING -i eth1 -p tcp –dport 80 -j DNAT –to-destination 192.168.0.1:80
我只解釋前四句,其它的可以man iptables
第一句打開(kāi)內核的ip轉發(fā)功能
后三句加載必要的模塊,當然如果這些模塊是靜態(tài)編譯進(jìn)內核的就不需要手動(dòng)加載了。
#cd ..
#tar zcf iptables.tar.gz iptables
#rm -rf iptables
調入和調出iptables的腳本我就不說(shuō)了,由前面的說(shuō)明你應該能夠輕松的寫(xiě)一個(gè)腳本出來(lái)。
5.9 根文件系統里面的最后一些東東
#cd var
#ls
empty lock log run
#touch run/utmp (who命令讀取的文件)
#touch log/wtmp (last命令用到的配置文件)
#touch log/lastlog (sshd開(kāi)啟登陸會(huì )話(huà)時(shí)讀取的文件)
#cd ..
#mkdir -p usr/share/terminfo/l
#cp /usr/share/terminfo/l/linux usr/share/terminfo/l
(linux為grub成功啟動(dòng)所需要的終端)
6.創(chuàng )建ramdisk
第5章已經(jīng)把根文件系統里面的內容做完了,現在我們建立ramdisk來(lái)存儲根文件系統。
#du -ks rootfs
8356
我們的rootfs有
#cd /mnt
#dd if=/dev/zero of=usblinux bs=
(前面提到讓ramdisk是虛擬的ram盤(pán),它是在內存中虛擬出一塊硬盤(pán),因此我們需要對其進(jìn)行格式化)
#mkfs.ext2 -m 0 usblinux
#mkdir usb
#mount -o loop usblinux usb
#cp -dpR /mnt/rootfs/* ./usb
#umount usb
#gzip -v9 usblinux
7 . 安裝kernel ,ramdisk,grub到u盤(pán)
要想從U盤(pán)啟動(dòng)linux,可能需要把U盤(pán)格式化成啟動(dòng)盤(pán),這里我們不關(guān)心這個(gè),我們已經(jīng)假定你的U盤(pán)可以以USB-HDD或者USB-ZIP方式啟動(dòng)。
插上準備好的U盤(pán)
#mount /dev/sda1 /mnt/usb (我這里的u盤(pán)設備是/dev/sda1,這個(gè)可以用fdisk -l命令查看)
#cd /mnt/usb
#mkdir boot/grub
#cp /usr/src/linux-2.4/arch/i386/boot/bzImage boot/usblinux.kernel
(把做好的內核拷貝到U盤(pán)上)
#cp /mnt/usblinux.gz boot/usblinux.img
(把做好的文件系統安裝到U盤(pán)上)
#cp /boot/grub/{stage1,stage2} boot/grub/
(在u盤(pán)上安裝grub需要用到的文件)
#vi boot/grub/grub.conf
default=0
timeout=10
title UsbLinux
root(hd0,0)
kernel /boot/usblinux.kernel ramdisk_size=13000 ro root=/dev/ram0
initrd /boot/usblinux.img
#cd ; umount /mnt/usb
最后一步就是安裝grub到u盤(pán)上了。
#grub
GNU GRUB version 0.95 (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 (hd1,0) (注,u盤(pán)所在的設備號,不同的系統可能不一樣,用fdisk -l先看看,不要搞錯了,另外,注意設備的命名規則)
grub>setup (hd1,0)
grub>quit
#
(注:關(guān)于grub的安裝及其使用可以參考grub手冊
http://www.gnu.org/software/grub/manual/grub.html#initrd)
到此為止,應該說(shuō)我們的目的基本完成了,不過(guò)啟動(dòng)的時(shí)候可能會(huì )出問(wèn)題,請查看faq。
8.Faq
1. 為什么我的usblinux啟動(dòng)后,到uncompressing usblinux.kernel…………booting the kernel 之后就沒(méi)有反應了呢?
答:這種情況我碰到的有兩個(gè)可能的原因
1) 內核的cpu型號選擇錯誤,譬如如果選擇athon的cpu,那么在奔4的或者賽楊的機器上跑就會(huì )出現這種情況。我們的內核cpu型號選擇i386就可以避免這種情況
2) 內核的Charater devices這一項里面沒(méi)有把Virtual terminal 以及support console on virtual terminal兩個(gè)選項編譯進(jìn)內核。
2. 內核為什么么啟動(dòng)到Free unused kernel memory *k,然后就沒(méi)有反應了?
答:如果cpu選擇386的話(huà),而lib庫還是使用的宿主機上的686的lib庫,那么就會(huì )出現這種情況,在red hat 9上glibc庫有386的版本和686的版本,我們需要從光盤(pán)上取出386的版本,然后用windows 下面的7zip工具把里面的相關(guān)庫文件去出來(lái),把我們的usblinux文件系統里面對應的庫文件換掉即可。
3. 為什么busybox的init啟動(dòng)之后,在啟動(dòng)getty的終端輸入root密碼總是提示出錯?
答:busybox的login/passwd認證有兩種方法,一個(gè)是使用它內部的認證方法,這是無(wú)需nsswitch.conf的支持,另外一種就是使用linux系統的認證,這時(shí)需要nsswitch.conf文件。我們的密碼一般放在/etc/shadow文件里面,但是我兩種方法試了都不行,也讓busybox支持了shadow,后來(lái)用askfirst動(dòng)作得到一個(gè)shell進(jìn)去之后,用passwd修改密碼才發(fā)現它的密碼是存在/etc/passwd里面的。
具體的修改密碼后passwd變成下面這樣的格式
root::$1$ccZny60u$o4MBUmzFjENUGWlVPKbTp.:0:0:root:/root:/bin/sh
而/etc/shadow文件里面的內容根本沒(méi)有任何變化。
下面你知道怎么解決這個(gè)問(wèn)題了吧。
4. 為什么我開(kāi)啟sshd服務(wù)后,遠程登陸輸入密碼后沒(méi)有反映了呢?
ssh遠程登陸到主機,需要主機的/dev/目錄下有ptyp*設備以及ttyp*設備,當然如果內核支持pts文件系統,那么也可以使用pts/* 設備。
聯(lián)系客服