说明:
        《一》:查看此博文,建议查看笔者上一篇博文(Linux启动过程),因为只有在完全了解Linux系统启动流程及一些配置文件的相关性,在阅读此博文才能有思路,理解起来更容易写。

        《二》:此博文主要讲解如何基于busybox制作一个属于自己的嵌入式Linux系统,及编译安装ngnix软件提供http功能,及利用dropbear提供SSH功能

提示:笔者在书写过程中难免发生书写错误,忘读者提出及谅解,笔者会在第一时间内修改内容。 

 


  1. 基于busybox制作微型嵌入式Linux系统:kernel(编译)+initrd(busybox)+/(busybox)+dropbear(提供SSH功能)  
  2.  
  3.  
  4. 操作环境表述:  
  5.     kernel版本:linux-2.6.38.5.tar.bz2(编译安装)-->http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.38.5.tar.bz2  
  6.     busybox版本:busybox-1.20.2.tar.bz2 --> http://www.busybox.net/downloads/busybox-1.20.2.tar.bz2   
  7.     dropbear:http://matt.ucc.asn.au/dropbear/dropbear.html/dropbear-2013.56.tar.bz2   
  8.  
  9.  
  10. busybox介绍:  
  11.     BusyBox 是一个集成了百多个最常用linux命令和工具的软件。  
  12.     BusyBox 包含了一些简单的工具(ls、cat、echo、touch......)及复杂的命令(grep、find、mount....)  
  13.     Busybox最初是由Bruce Perens在1996年为Debian GNU/Linux安装盘编写,简单的说BusyBox就是个百宝箱,它集成压缩了Linux系统中的许多工具和命令。  
  14.       
  15. dropbear(开源软件)介绍:  
  16.     dropbear是一个相对较小的SSH服务器和客户端软件,运行在一个基于POSIX的各种平台,dropbear实现完整的SSH S/C版本2协议。  
  17.     简单说dropbear就是一款开源的轻量级SSH服务软件。(笔者理解)  
  18.  
  19.  
  20.  
  21. 实现步骤:  
  22. 1、添加一块IDE硬盘(10G),并对其进行分区(/dev/hda1(20M)、/dev/hda2(512M)、/dev/hda3(128M)->将/dev/hda3的文件类型改为82即可)  
  23.    文件类型均为ext3(mke2fs -j /dev/hda#),可以参考笔者写的RAID的原理及一步步来实现RAID的创建 (里面有关于创建分区及更改分区文件系统类型案例)  
  24.     # fdisk /dev/hda (/dev/hda分区)  
  25.     # partprobe /dev/hda  
  26.     # mke2fs -j /dev/hda#  
  27.  
  28.  
  29. 2、创建目录作为/dev/hda1、/dev/hda2挂载点并进行挂载  
  30.     # mkdir /mnt/{boot,sysroot} -pv  
  31.     # tree /mnt     ##查看/mnt目录下的所有文件及其子目录  
  32.     # mount /dev/hda1 /mnt/boot       ##用于Linux启动分区  
  33.     # mount /dev/hda2 /mnt/sysroot    ##用于Linux根分区  
  34.     # mount       ##可以使用mount命令查看是否挂载成功  
  35.  
  36.  
  37. 3、编译内核源代码,作为新系统提供所需的内核(源代码包都位于/usr/src目录中)  
  38.     # cd  /usr/src  
  39.     # tar jxvf linux-2.6.38.5.tar.bz2    ##解压源代码这里下载的bzip格式压缩的,所以使用j选项  
  40.     # ln  -sv  linux-2.6.38.5  linux      ##给linux-2.6.38.5做个软连接其命名为linux  
  41.     # cd linux  
  42.     # cp /root/kernel-2.6.38.1-i686.cfg   ./.config  ##kernel-2.6.38.1-i686.cfg(2.6.38系统所使用的模块,可以修改一些模块)  
  43.     # make menuconfig         
  44. 说明:在这里我们将文件系统中的ext3、网卡的驱动程序直接编译进内核,因为笔者使用的是vmware Workstation虚拟机 ,所以网卡类型为pcnet32  
  45.         
  46.     # make  SUBDIR=arch/       
  47.     # cp arch/x86/boot/bzImage  /mnt/boot/  ##将我们编译安装好的内核文件复制到/mnt/boot目录  
  48.       
  49.       
  50. 4、编译安装busybox(busybox-1.20.2.tar.bz2)  
  51. 说明:busybox需要比较新的内核支持头文件中的ubi-user.h,  
  52.     所以我们要将这个文件复制到/usr/src/busybox-1.20.2/iniclued/mtd即可  
  53.     # cd /usr/src  
  54.     # tar  jxvf  busybox-1.20.2.tar.bz2  
  55.     # cd  busybox-1.20.2  
  56.     # mkdir include/mtd     
  57.     # cp  /usr/src/linux/include/mtd/ubi-user.h  include/mtd/  
  58.     # make menuconfig    ## 参考“说明”  
  59.     # make install     
  60. 说明:  
  61. 1、  此处需要选择 Busybox Settings --> Build Options -->  Build BusyBox as a static binary (no shared libs),这样可以把Busybox编译成一个不使用共享库  
  62.     的静态二进制文件,从而避免了对宿主机的共享库产生依赖,但你也可以不选择此项,而完成编译后把其依赖的共享库复制至目标系统上的/lib目录中即可;  
  63.       
  64. 2、  修改安装位置为/mnt/sysroot;方法为:Busybox Settings --> Installation Options --> (./_install) BusyBox installation prefix,  
  65.     修改其值为/mnt/sysroot,默认安装在当当前目录,其命名为_install  
  66.  
  67. 说明:安装后的文件均位于/mnt/sysroot目录中,但为了创建initrd(虚拟根文件系统),并实现让其启动以后将真正切换至目标系统分区上的rootfs,  
  68.      这里我们创建个临时目录(/tmp/busybox)使用,  
  69.     # mkdir -pv /tmp/busybox      ##创建临时目录,用于制作虚拟根文件系统  
  70.     # cp -r /mnt/sysroot/*  /tmp/busybox -a  
  71.     # cd /tmp/busybox  ##进入临时目录将linuxrc链接文件删除  
  72.     # mkdir proc sys etc dev mnt/sysroot tmp lib/modules -pv     
  73.     # vim init   
  74.         mount -t proc proc /proc  
  75.         mount -t sysfs sysfs /sys  
  76.         mdev -s  
  77.         mount -t ext3 /dev/hda2  /mnt/sysroot  
  78.         exec  switch_root  /mnt/sysroot  /sbin/init  
  79.     :wq  
  80.     # chmod +x init  
  81.       
  82.  
  83.       
  84. 3、创建两个必要的设备文件:  
  85.     # mknod  dev/console  c  5  1  
  86.     # mknod  dev/null  c  1  3  
  87.  
  88. 4、制作initrd  
  89.     # find  .  | cpio  --quiet  -H newc  -o  | gzip  -9 -n > /mnt/boot/initrd.gz  
  90.  
  91. 5、建立真正根文件系统(rootfs)  
  92.     # cd /mnt/sysroot  
  93.     # mkdir -pv  proc  sys  etc/rc.d/init.d  tmp  dev/pts  boot  var/log  usr/lib  
  94.     # mknod  dev/console  c  5  1  
  95.     # mknod  dev/null  c  1  3  
  96.     # vim etc/rc.d/init.d/functions  ##定义函数用于其它脚本调用(内容如下:)  
  97.     #!/bin/bash  
  98.     A=`stty -F /dev/console size &>/dev/null`  ##显示的是我们终端支持横和列,默认(25 80)  
  99.     lie=${A#* }  
  100.     [ -z $lie ] && lie=80  
  101.     space=$[$lie-14]  
  102.  
  103.     RED='\033[31m' 
  104.     GREEN='\033[32m' 
  105.     NORMAL='\033[0m' 
  106.     success() {  
  107.         string=$1  
  108.         RT_SPA=$[$space-${#string}]  
  109.         echo -n "$string" 
  110.     for I in `seq 1 $RT_SPA`;do  
  111.        echo -n " " 
  112.     done  
  113.     echo -e "[  ${GREEN}OK${NORMAL}  ]" 
  114.     }  
  115.     failure() {  
  116.         string=$1  
  117.         RT_SPA=$[$space-${#string}]  
  118.         echo -n "$string" 
  119.     for I in `seq 1 $RT_SPA`;do  
  120.        echo -n " " 
  121.     done  
  122.     echo -e "[  ${RED}FAILED${NORMAL}  ]" 
  123.     }  
  124.     :wq  
  125.     # chmod +x etc/rc.d/init.d/functions  
  126.     创建系统初始化rc.sysinit脚本  
  127.     # vim  etc/rc.d/rc.sysinit  
  128.     #!/bin/bash  
  129.     echo -e "\tWelcome to  \033[31mMageEdu\033[0m Linux" 
  130.     . /etc/rc.d/init.d/functions              ##读取functions函数到etc/rc.d/rc.sysinit  
  131.     success "Remounting the root filesystem ..." 
  132.     mount -t proc proc /proc  
  133.     mount -t sysfs sysfs /sys  
  134.     mount -o  remount,rw  /   
  135.  
  136.     mdev -s   
  137.     success "Creating the files of device ..." 
  138.  
  139.     mount -a  
  140.     swapon -a  
  141.     success "Mounting the filesystem ..." 
  142.       
  143.     syslogd  
  144.     klogd  
  145.     success "Starting the log daemon ..." 
  146.  
  147.     ifconfig  lo  127.0.0.1/24  
  148.     ifconfig eth0 172.16.100.9/16  
  149.     success "Configuring loopback interface ..." 
  150.     :wq  
  151.     # chmod +x etc/rc.d/rc.sysinit  
  152.  
  153. 6、配置init及其所需要inittab文件  
  154.     # cd  /tmp/busybox  
  155.     # rm  -f  linuxrc  
  156.     # vim  etc/inittab  
  157. 添加如下内容:  
  158. ::sysinit:/etc/rc.d/rc.sysinit  
  159. console::respawn:-/bin/sh  
  160. ::ctrlaltdel:/sbin/reboot  
  161. ::shutdown:/bin/umount -a -r  
  162. :wq  
  163.  
  164. 7、为系统准备一个“文件系统表”配置文件/etc/fstab  
  165. # vim  etc/fstab  
  166. 添加如下内容:  
  167. sysfs                   /sys                    sysfs   defaults        0 0  
  168. proc                    /proc                   proc    defaults        0 0  
  169. /dev/hda1               /boot                   ext3    defaults        0 0  
  170. /dev/hda2               /                       ext3    defaults        1 1  
  171. :wq  
  172.  
  173.  
  174. 8、下面就可以为系统创建所需的引导程序grub了  
  175.     # grub-install  --root-directory=/mnt  /dev/hda  
  176.  
  177. 9、为grub建立配置文件,让系统引导grub所定义的配置文件:  
  178.     # vim  /mnt/boot/grub/grub.conf  
  179. 添加如下内容:(这里只做了简单的定义)  
  180.     default=0           ## 设定默认启动的title的编号,从0开始  
  181.     timeout=3           ## 等待用户选择的超时时长,单位是秒  
  182.     title   MyLinx system (2.6.38.5)          ## 内核标题,或操作系统名称,字符串,可自由修改  
  183.         root (hd0,0)    # 内核文件所在的设备;对grub而言,所有类型硬盘一律hd,格式为(hd#,N);hd#, #表示第几个磁盘;最后的N表示对应磁盘的分区;  
  184.         kernel /bzImage ro root=/dev/hda2 quiet        # 内核文件路径,及传递给内核的参数  
  185.         initrd /initrd.gz         ##这是我们给予busybox制作的虚拟根文件系统  
  186.     :wq  
  187.       
  188.     现在我们来做个测试:  
  189. 说明:  
  190.     这里我们的实验环境用的vmware Workstation,所以我们重新创建个虚拟机:步骤如下:  
  191.     点击:File->New Virtual Machine..(ctrl+n)->Custom(advanced)->Next->(default)Next->(default)Next->更改Guest opevating system选项改为linux,然后将  
  192.     Version版本改为Red Hat Enterprise Linux 5 ->Next->保持默认也可作相应的设置->Next->设置内存为64即可->选择桥接方式(这里我们使用第一选项)->Next->  
  193.     选择硬盘,这里我们选择第二选项(就是已存在的磁盘)-Next->浏览我们虚拟机添加的那块IDE硬盘即可->Finish  
  194.       
  195. 下面我们来做下扩张内容:  
  196.  
  197. 1、为新构建的微型Linux启用虚拟控制台  
  198.     # cd /mnt/sysroot  
  199.     将 etc/inittab文件改为如下内容:  
  200.     ::sysinit:/etc/init.d/rc.sysinit  
  201.     tty1::askfirst:/bin/sh  
  202.     tty2::askfirst:/bin/sh  
  203.     tty3::askfirst:/bin/sh  
  204.     tty4::askfirst:/bin/sh  
  205.     tty5::askfirst:/bin/sh  
  206.     tty6::askfirst:/bin/sh  
  207.     ::ctrlaltdel:/sbin/reboot  
  208.     ::shutdown:/bin/umount -a -r  
  209.     :wq            
  210. 注:因为我们使用的是busybox制作的根文件系统,所以关于init所使用的配置文件/etc/inittab的格式有所不同。  
  211.       
  212. 2、已经实现了虚拟控制台,但其仍是直接进入系统,且系统没有用户帐号等安全设施,所以接下来的工作就是实现为系统用户添加账号(以root为例)  
  213.     我们知道关于用户都会设置到一下文件:  
  214.         /etc/passwd   
  215.         /etc/group 
  216.         /etc/shadow  
  217. 步骤如下:  
  218. (1)、为目标主机建立passwd帐号文件  
  219.     # cd /mnt/sysroot  
  220.     # vim etc/passwd  
  221. 添加如下内容:  
  222.     root:x:0:0::/root:/bin/sh  
  223. :wq  
  224.     # mkdir root    ##为root用户创建“家”目录:  
  225.  
  226. (2)、为目标主机建立group帐号文件  
  227.     # vim  etc/group 
  228. 添加如下内容:  
  229.     root:x:0:  
  230. :wq  
  231.  
  232. (3)、为目标主机建立shadow影子口令文件,这里采用直接复制宿主机的shadow文件中关于root口令行的行来实现  
  233. # grep  "^root"  /etc/shadow  > etc/shadow  
  234.  
  235. 注:等目标主机启动时,root用户的口令也是宿主机的root用户的口令。您可以在目标主机启动以后再动手更改root用户的口令。  
  236.     更改口令命令为:  
  237.     # passwd  
  238.  
  239. 这样就是可以实现用户的登陆:  
  240.  
  241. 下面我们在进一步扩展,让我们真正了解linux的启动流程  
  242.  
  243. 注:一下更改就在宿主机上完成  
  244.  
  245. 1、为系统登录时提供banner信息  
  246. 注:我们知道提供banner信息所使用的配置文件为/etc/issue,直接在/mnt/sysroot/etc/创建issue文件  
  247. 这个可以通过宿主机来实现,也可以直接在目标主机上进行配置。  
  248.     # vi  /etc/issue  
  249. 添加如下内容:  
  250.     Welcome to http://www.magedu.com   ##欢迎信息  
  251.     Kernel \r  
  252. 注:这里的内容可以根据你的需要显示的内容进行修改相应修改  
  253.  
  254.  
  255. 2、在系统启动时为系统提供主机名称:  
  256. (1)、创建保存主机名称的配置文件  
  257.     # mkdir /etc/sysconfig  
  258.     # vi  /etc/sysconfig/network  
  259. 添加如下内容:  
  260.     HOSTNAME=www.magedu.com  
  261. :wq  
  262.  
  263. (2)、编辑系统初始化脚本,实现开机过程中设定主机名称  
  264.     # vi /etc/init.d/rc.sysinit  
  265.     添加如下内容:  
  266.     HOSTNAME=  
  267.     [ -e  /etc/sysconfig/network  && -r /etc/sysconfig/network ] && . /etc/sysconfig/network  
  268.     [ -z ${HOSTNAME} ] && HOSTNAME="localhost" 
  269.     /bin/hostname  ${HOSTNAME}  
  270. :wq  
  271.  
  272. 这样,我们的制作的微型嵌入式Linux系统就完善了许多。  
  273. 下面,我们使用dropbear软件实现远程SSH连接(SHH2)  
  274.  
  275. 1、通过dropbear为系统提供ssh远程连接服务  
  276. 1、编译安装dropbear  
  277.     # cd /usr/src  
  278.     # tar xf dropbear-2013.56.tar.bz2   
  279.     # cd dropbear-2013.56  
  280.     # ./configure   
  281.     # make  
  282.     # make install  
  283.  
  284. 2、移植dropbear至目标系统  
  285.  
  286. 下面我们来写一个脚本,脚本功能实现二进制程序及二进制文件所依赖的库文件复制到/mnt/syroot/bin及/mnt/sysroot/lib目录中,脚本如下:  
  287. #!/bin/bash  
  288. #  
  289. read -t 30 -p "Target System Directory[/mnt/sysroot]: " DEST  
  290. DEST=${DEST:-/mnt/sysroot}  
  291.  
  292. libcp() {  
  293.   LIBPATH=${1%/*}    ##截取机名   如/bin/bash 所显示的结果为bash  
  294.   [ ! -d $DEST$LIBPATH ] && mkdir -p $DEST$LIBPATH  
  295.   [ ! -e $DEST${1} ] && cp $1 $DEST$LIBPATH && echo "copy lib $1 finished." 
  296. }                              
  297.              #判读目录是否存在,如果不存在则创建,存在将二进制命令复制到相对目录下  
  298. bincp() {  
  299.   CMDPATH=${1%/*}  
  300.   [ ! -d $DEST$CMDPATH ] && mkdir -p $DEST$CMDPATH  
  301.   [ ! -e $DEST${1} ] && cp $1 $DEST$CMDPATH  
  302.              ## 判断我们输入的命令所依赖的库目录是否存在,不存在则创建,存在则执行复制工作。  
  303.  
  304.   for LIB in  `ldd $1 | grep -o "/.*lib\(64\)\{0,1\}/[^[:space:]]\{1,\}"`; do  
  305.     libcp $LIB  
  306.   done  
  307. }                   ##使用ldd命令常看二进制程序所用到的库文件,并执行复制工作  
  308.  
  309. read -p "Your command: " CMD  
  310. until [ $CMD == 'q' ]; do  
  311.    ! which $CMD && echo "Wrong command" && read -p "Input again:" CMD && continue 
  312.   COMMAND=` which $CMD | grep -v "^alias" | grep -o "[^[:space:]]\{1,\}"`  
  313.   bincp $COMMAND  
  314.   echo "copy $COMMAND finished." 
  315.   read -p "Continue: " CMD  
  316. done          ##调用bincp函数来执行操作  
  317.     # chmod +x bincp.sh(脚本名称)  
  318. 好了,接下来就运行bincp.sh脚本将,输入dropbear、dropbearkey和dbclient即可;这些命令会被存储于目标系统的/usr/local/sbin或/usr/local/bin目录中。  
  319.  
  320. 3、为远程登录的用户提供伪终端设备文件  
  321.     # vim /mnt/sysroot/etc/fstab,添加如下一行:  
  322.     devpts      /dev/pts        devpts  mode=620    0 0  
  323.     :wq  
  324. 创建所需要的目录:  
  325.     # mkdir /mnt/sysroot/dev/pts  
  326.       
  327. 4、为目标系统的dropbear生成主机密钥  
  328. 默认情况下,dropbear到/etc/dropbear目录中查找使用的rsa格式主机密钥(默认名称为dropbear_rsa_host_key)和dss格式的主机密钥  
  329.     (默认名称为dropbear_dss_host_key)。其中,rsa格式可使用不同长度的密钥,但dss格式只使用1024位的密钥。  
  330.  
  331.     # mkdir /mnt/sysroot/etc/dropbear  
  332.     # dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key -s 2048  
  333.     # dropbearkey -t rsa -f /etc/dropbear/dropbear_dss_host_key  
  334.  
  335. 在生成rsa格式的key时,其长度指定部分-s 2048可以省略,也可以为其指定为其它长度,但长度需要为8的整数倍。  
  336. 说明:此步骤也可以在目标主机上进行,但路径要做相应的修改。  
  337.  
  338. 5、定义安全shell  
  339.     安全起见,dropbear默认情况下仅允许其默认shell出现在/etc/shells文件中的用户远程登录,因此,这里还需要创建/etc/shells文件,并添加所有允许的shell。  
  340.     # cat >> /mnt/sysroot/etc/shells << EOF  
  341.     /bin/sh  
  342.     /bin/ash  
  343.     /bin/hush  
  344.     /bin/bash  
  345.     EOF  
  346.  
  347. 6、为目标主机提供网络服务转换机制  
  348. 在宿主机上使用默认选项编译的dropbear将依赖nsswitch实现用户名称解析,因此,还需要为目标主机提供nss相关的库文件及配置文件。  
  349.  
  350.     # cat >> /mnt/sysroot/etc/nsswitch.conf << EOF  
  351.     passwd:     files  
  352.     shadow:     files  
  353.     group:      files  
  354.     hosts:      files dns  
  355.     EOF  
  356.       
  357. 复制所需要的库文件:  
  358. # cp -d /lib/libnss_files*  /mnt/sysroot/lib/  
  359. # cp -d /usr/lib/libnss3.so /usr/lib/libnss_files.so /mnt/sysroot/usr/lib/  
  360.  
  361. 7、由于在rc.sysinit文件中启动了日志进程,因此系统在运行中会产生大量日志并将其显示于控制台;  
  362.     # vim  etc/syslog.conf  
  363.     添加如下一行:  
  364.     *.info    /var/log/messages  
  365.     :wq  
  366. 说明: 由于在rc.sysinit文件中启动了日志进程,因此系统在运行中会产生大量日志并将其显示于控制台;  
  367.         这将会经常性的打断正在进行的工作,为了避免这种情况,我们这里为日志进程建立配置文件,为其指定将日志发送至/var/log/messages文件;  
  368.       
  369.  
  370.  
  371. 8、测试  
  372. 启动目标主机,设定好网络属性后,使用如下命令启动dropbear服务即可。  
  373. # /usr/local/sbin/dropbear  
  374. 接下来就可以远程进行连接测试了。  
  375.  
  376. 接下来我们实现一个基于nginx软件,来为我们制作的微型Linux系统提供www服务  
  377.  
  378. 通过nginx提供web服务  
  379.  
  380. 1、在宿主机编译安装nginx-1.2.5  
  381. # tar nginx-1.2.5.tar.gz  
  382. # cd nginx-1.2.5  
  383. # ./configure --prefix=/usr/local --conf-path=/etc/nginx/nginx.conf  --error-log-path=/var/log/nginx/error.log --user=nginx --group=nginx --http-log-path=/var/log/nginx/access.log  --without-pcre --without-http_rewrite_module --without-http_geo_module --without-http_fastcgi_module  --without-http_uwsgi_module  --without-http_scgi_module --without-http_memcached_module --without-http_upstream_ip_hash_module --without-http_upstream_least_conn_module  --without-http_upstream_keepalive_module --http-log-path=/var/log/nginx  
  384. # make  
  385. # make install  
  386.  
  387. 2、移植nginx至目标系统  
  388.  
  389. (1) 移植二进制程序及其依赖的库文件,方能实现其在目标系统上正常运行。建议使用前面的bincp.sh脚本进行。  
  390.  
  391. (2) 移植配置文件至目标系统  
  392. # mkdir  /mnt/sysroot/etc/nginx/  
  393. # cp /etc/nginx/{nginx.conf,mime.types}  /mnt/sysroot/etc/nginx/  
  394.  
  395. (3) 移植测试页面至目标系统,当然,也可以不采用下面的步骤而在目标系统上直接创建。  
  396. # mkdir /mnt/sysroot/usr/local/  
  397. # cp -r /usr/local/html  /mnt/sysroot/usr/local/  
  398.  
  399. 3、测试  
  400.  
  401. 启动目标主机,首先配置好网络属性,并使用adduser为其添加nginx用户和nginx组。  
  402.  
  403. 然后使用如下命令启动nginx  
  404. # /usr/local/nginx  
  405.  
  406. 测试命令  
  407. #elinks IPADDR即可在我们制作的LINUX系统上进行测试啦。  
  408.  
  409.  
  410.