原文
前言
一個(gè)定制的linux內(nèi)核+一個(gè)定制的busybox就可以定制一個(gè)小型的Linux操作系統(tǒng)了,安裝Dropbear和Nginx,Linux的組成 部分包括內(nèi)核空間和用戶空間、而用戶空間其實(shí)就是根文件系統(tǒng)、用戶空間中又包括有shell和init,busybox他能夠模擬數(shù)百個(gè)我們系統(tǒng)上帶用的 命令、當(dāng)然包括我們所需要用到的shell、init、getty、login、那定制一個(gè)Linux操作系統(tǒng)我們必須要了解的就是系統(tǒng)啟動(dòng)流程: # fdisk /dev/sdb n p 1 +50M n p 2 +512M n p 3 +256M t 3 82 w # mke2fs -t etx4 /dev/sdb1 # mke2fs -t etx4 /dev/sdb2 # mkswap /dev/sdb3 # mkdir -pv /mnt/{boot,sysroot} # mount /dev/sdb1 /mnt/boot # mount /dev/sdb2 /mnt/sysroot 第一步:編譯內(nèi)核或定制內(nèi)核 1、獲取內(nèi)核程序包,可以到官網(wǎng)下載:https://www./、這里我們使用的內(nèi)核版本是3.13.6的版本: # tar xf linux-3.13.6.tar.xz -C /usr/src/ # cd /usr/src # ln -sv linux-3.13.6 linux # cd linux # make allnoconfig # make menuconfig 把我們所需要的內(nèi)容整合進(jìn)來 我們把這些內(nèi)容全部編譯進(jìn)內(nèi)核、不編譯成模塊、*號表示編譯進(jìn)內(nèi)核 [*]64-bit kernel :64位操作系統(tǒng)的內(nèi)核 General setup --> Local version --> -MyLinux: 給內(nèi)核定一個(gè)自己的版本 Processor type and features --> Processor family --> (X)Generic-x86-64:這里是CPU類型、這個(gè)是通用x86-64 [*]Symmetric multi-processing support:選擇CPU支持多核心處理 [*]Enable loadable module support:選擇內(nèi)核動(dòng)態(tài)模塊加載 Bus options (PCI etc.) --> [*]PCI suppor:支持PCI總線 Device Drivers --> <*>SCSI device support -->[*]SCSI disk support要支持SCSI硬盤 Device Drivers -->Fusion MPT device support (NEW) --> <*>Fusion MPT ScsiHost drivers for SPI、<*>Fusion MPT misc device (ioctl) driver、[*]Fusion MPT logging facility:支持對硬盤的驅(qū)動(dòng) File systems --> <*>The Extended 4 (ext4) filesystem:支持文件系統(tǒng) Executable file formats / Emulations --> [*]Kernel support for ELF binaries、[*]Write ELF core dumps with partial segments (NEW)、 <*>Kernel support for scripts starting with #!:可執(zhí)行文件的格式 Device Drivers -->Input device support --> [*]Keyboards -> <*>AT keyboard (NEW) [*]Mice:支持輸入輸出設(shè)備、比如健盤 Device Drivers > USB support > <*>UHCI HCD (most Intel and VIA) support、<*>OHCI HCD (USB 1.1) support、<*>EHCI HCD (USB 2.0) support:USB設(shè)備驅(qū)動(dòng) Device Drivers > Generic Driver Options > [*] Maintain a devtmpfs filesystem to mount at /dev [*]Automount devtmpfs at /dev, after the kernel mounted the rootfs Networking support > Networking options[*] TCP/IP networking [*]IP:multicasting [*]IP: advanced router[*]IP: policy routing [*]IP: verbose route monitoring[*] IP: kernel level autoconfiguration[*]IP: DHCP support[*]IP: BOOTP support[*] IP: RARP support<*>IP: tunneling <*>Unix domain sockets<*> UNIX: socket monitoring interface:支持協(xié)議 Device Drivers > Network device support > Ethernet driver support[*]Intel devices (NEW)<*>Intel(R) PRO/1000 Gigabit Ethernet support<*>Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support:只要Intel的、其他的他都去掉、這是選擇網(wǎng)卡設(shè)備的驅(qū)動(dòng)程序 [ ]Wireless:這個(gè)無線網(wǎng)、我們?nèi)サ羧?、用不?/span> OK、到這里保存退出、把配置文件復(fù)制一份出來、前面磁盤格式化而且都掛載好了、這里我們就把grub安裝到boot下:: # cp .config /root/config-3.13.6-x86_64 # make bzImage # cp arch/x86/boot/bzImage /mnt/boot/ # grub-install --root-directory=/mnt /dev/sdb BusyBox 的誕生BusyBox 最初是由 Bruce Perens 在 1996 年為 Debian GNU/Linux 安裝盤編寫的。其目標(biāo)是在一張軟盤上創(chuàng)建一個(gè)可引導(dǎo)的 GNU/Linux 系統(tǒng),這可以用作安裝盤和急救盤。一張軟盤可以保存大約 1.4-1.7MB 的內(nèi)容,因此這里沒有多少空間留給 Linux 內(nèi)核以及相關(guān)的用戶應(yīng)用程序使用。 BusyBox 揭露了這樣一個(gè)事實(shí):很多標(biāo)準(zhǔn) Linux 工具都可以共享很多共同的元素。例如,很多基于文件的工具(比如 BusyBox 編譯選項(xiàng)BusyBox 包括了幾個(gè)編譯選項(xiàng),可以幫助為我們編譯和調(diào)試正確的 BusyBox。 表 1. 為 BusyBox 提供的幾個(gè) make 選項(xiàng)
在定義配置時(shí),我們只需要輸入 $ make allyesconfig $ make 編譯Busybox 、讓busybox提供一個(gè)sh程序、busybox可以模擬n種sh、可以模擬bash的特性、上面我們有介紹過他了。 # yum -y install libmcrypt-devel # rpm --install glibc-static-2.12-1.132.el6.x86_64.rpm # tar xf busybox-1.22.1.tar.bz2 # cd busybox-1.22.1 # make menuconfig # make # make install make menuconfig時(shí)就選擇這項(xiàng)就可以了、其他的都使用默認(rèn)的吧: # cp -a _install/* /mnt/sysroot/ # cd /mnt/sysroot/ # mkdir -pv /etc/rc.d var/log root home lib lib64 dev proc sys boot mnt media tmp srv 給grub提供一個(gè)配置文件 # vim /mnt/boot/grub/grub.conf default=0 timeout=5 title Mini Linux (3.13.6-MyLinux) root (hd0,0) kernel /bzImage ro root=/dev/sda2 init=/sbin/init 給小系統(tǒng)提供一個(gè)rc.sysinit、/mnt/sysroot/etc/rc.d/rc.sysinit、如果沒有這個(gè)目錄就自己創(chuàng)建、再提供一個(gè)/mnt/sysroot/etc/fstab文件 # vim /mnt/sysroot/etc/fstab /dev/sda1 /boot ext4 defaults 0 0 proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 /dev/sda2 / ext4 defaults 0 0 /dev/sda3 swap swap defaults 0 0 # mkdir -p /mnt/sysroot/etc/rc.d/rc.sysinit #!/bin/sh # 打印系統(tǒng)啟動(dòng)時(shí)的歡迎信息 echo -e "\tWecome to \033[34mMini\033[0m Linux" 判斷/etc/sysroot/network是否存在并且可讀、條件成立就source進(jìn)來 [ -r /etc/sysconfig/network ] && . /etc/sysconfig/network 判斷$HOSTNAME是否為空并且$HOSTNAME==NONE、如果為空就給個(gè)默認(rèn)值 [ -z "$HOSTNAME" -o "$HOSTNAME" == "(none)" ] && HOSTNAME=localhost 給HOSTNAME賦值為定義好的HOSTNAME的值 /bin/hostname $HOSTNAME 掛載文件系統(tǒng) echo "mounting proc filesystem..." mount -t proc proc /proc echo "mounting sysfs filesystem..." mount -t sysfs sysfs /sys 自動(dòng)探測各硬件設(shè)備、并且能夠探測到的都裝載設(shè)備文件 mdev -s 給系統(tǒng)配置一個(gè)IP地址 ifconfig lo 127.0.0.1 ifconfig eth0 172.16.254.188 mount -a mkdir /dev/pts mount -t devpts devpts /dev/pts # vim /mnt/sysroot/etc/inittab ::sysinit:/etc/rc.d/rc.sysinit 明確指定要找/etc/rc.d/rc.sysinit文件 ::respawn:/sbin/getty 19200 tty1 ::respawn:/sbin/getty 19200 tty2 ::respawn:/sbin/getty 19200 tty3 ::respawn:/sbin/getty 19200 tty4 ::respawn:/sbin/getty 19200 tty5 ::respawn:/sbin/getty 19200 tty6 :19200表示每秒鐘傳輸?shù)乃俾?、getty是一個(gè)串型終端、他會(huì)調(diào)用一個(gè)登錄界面讓用戶輸入登錄信息進(jìn)行驗(yàn)證 tty6::askfirst:/bin/sh 啟用6個(gè)虛擬終端 console::respawn:-/bin/sh 啟用一個(gè)終端,如果出錯(cuò)重新啟動(dòng)respawn、-表示敲一回車才可以啟用sh ::ctrlaltdel:/sbin/reboot 定義組合鍵、按ctrl+alt+del就reboot ::shutdown:/bin/umount -a -r 如果要要關(guān)機(jī)就卸載已掛載的設(shè)備、然后關(guān)機(jī) 提供系統(tǒng)用戶登錄賬號文件: # useradd busybox # passwd busybox 密碼也設(shè)置為:busybox # head -1 /etc/passwd > /mnt/sysroot/etc/passwd # tail -1 /etc/passwd >> /mnt/sysroot/etc/passwd # vim /mnt/sysroot/etc/passwd root:x:0:0:root:/root:/bin/sh busybox:x:502:503::/home/busybox:/bin/sh # head -1 /etc/group > /mnt/sysroot/etc/group # tail -1 /etc/group >> /mnt/sysroot/etc/group # head -1 /etc/shadow > /mnt/sysroot/etc/shadow # tail -1 /etc/shadow >> /mnt/sysroot/etc/shadow # cat /mnt/sysroot/etc/shadow 提供一個(gè)登錄歡迎信息、創(chuàng)建一個(gè)issue文件 # vim /mnt/sysroot/etc/issue MyLinux is CentOS release 6.5 Kernel \r on an \m 提供主機(jī)名 # mkdir /mnt/sysroot/etc/sysconfig # vim /mnt/sysroot/etc/sysconfig/network HOSTNAME=mylinux.tanxw.com 提供命令提示符和環(huán)境變量 # vim /mnt/sysroot/etc/profile export PS1='[\u@\h \A \W]\$ ' PATH="/usr/local/sbin:/usr/local/bin:/sbin/:/bin:/usr/sbin:/usr/bin:$PATH" # chmod +x /mnt/sysroot/etc/rc.d/rc.sysinit # sync 同步數(shù)據(jù)到磁盤中去 到這里我們的配置算是有個(gè)大概了、那就把宿主機(jī)掛起、創(chuàng)建一個(gè)自定義虛擬機(jī)、把我們制作有系統(tǒng)的那張硬盤放到自定義的虛擬機(jī)上運(yùn)行: 如果第一個(gè)終端登錄不了可以切換到其他終端上登錄,按ctrl+alt+F2(F3\F4\F5\F6)可以切換到不同的終端上去登錄的、這里我們登錄成功了:
1、解壓安裝dropbear # tar xf dropbear-2013.58.tar.bz2 # cd dropbear-2013.58 # ./configure # make # make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install # mkdir /etc/dropbear 生成兩個(gè)密鑰文件 # dropbearkey -t rsa -s 1024 -f /etc/dropbear/dropbear_rsa_host_key # dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key 驗(yàn)證一下生的這兩個(gè)文件 # ls /etc/dropbear 2、服務(wù)腳本/etc/rc.d/init.d/dropbear #!/bin/bash # # description: dropbear ssh daemon # chkconfig: 2345 66 33 # dsskey=/etc/dropbear/dropbear_dss_host_key rsakey=/etc/dropbear/dropbear_rsa_host_key lockfile=/var/lock/subsys/dropbear pidfile=/var/run/dropbear.pid dropbear=/usr/local/sbin/dropbear dropbearkey=/usr/local/bin/dropbearkey [ -r /etc/rc.d/init.d/functions ] && . /etc/rc.d/init.d/functions [ -r /etc/sysconfig/dropbear ] && . /etc/sysconfig/dropbear keysize=${keysize:-1024} port=${port:-22} gendsskey() { [ -d /etc/dropbear ] || mkdir /etc/dropbear echo -n "Starting generate the dss key: " $dropbearkey -t dss -f $dsskey &> /dev/null RETVAL=$? if [ $RETVAL -eq 0 ]; then success echo return 0 else failure echo return 1 fi } genrsakey() { [ -d /etc/dropbear ] || mkdir /etc/dropbear echo -n "Starting generate the rsa key: " $dropbearkey -t rsa -s $keysize -f $rsakey &> /dev/null RETVAL=$? if [ $RETVAL -eq 0 ]; then success echo return 0 else failure echo return 1 fi } start() { [ -e $dsskey ] || gendsskey [ -e $rsakey ] || genrsakey if [ -e $lockfile ]; then echo -n "dropbear daemon is already running: " success echo exit 0 fi echo -n "Starting dropbear: " daemon --pidfile="$pidfile" $dropbear -p $port -d $dsskey -r $rsakey RETVAL=$? echo if [ $RETVAL -eq 0 ]; then touch $lockfile return 0 else rm -f $lockfile $pidfile return 1 fi } stop() { if [ ! -e $lockfile ]; then echo -n "dropbear service is stopped: " success echo exit 1 fi echo -n "Stopping dropbear daemon: " killproc dropbear RETVAL=$? echo if [ $RETVAL -eq 0 ]; then rm -f $lockfile $pidfile return 0 else return 1 fi } status() { if [ -e $lockfile ]; then echo "dropbear is running..." else echo "dropbear is stopped..." fi } usage() { echo "Usage: dropbear {start|stop|restart|status|gendsskey|genrsakey}" } case $1 in start) start ;; stop) stop ;; restart) stop start ;; status) status ;; gendsskey) gendsskey ;; genrsakey) genrsakey ;; *) usage ;; esac 3、腳本配置文件/etc/sysconfig/dropbear keysize=2048 port=22022 # chmod +x /etc/rc.d/init.d/dropbear # chkconfig --add dropbear # vim /etc/profile.d/dropbear.sh export PATH=/usr/local/sbin:$PATH 啟動(dòng)服務(wù)并查看端口22022是否已經(jīng)處于監(jiān)聽狀態(tài)、并在本地嘗試連接登錄: # service dropbear start # ss -tnl
OK了、dropbear在本機(jī)安裝成功并且成功啟動(dòng)連接上去了、 那我們就移植到我們的定制系統(tǒng)上去吧、之前我們寫過一個(gè)腳本用來移植命令的: #!/bin/bash # dirPath=/mnt/sysroot clearcmd(){ if which $1 &> /dev/null;then cmdPath=`which --skip-alias $1` else echo "Command not exist!" return 4 fi } cpCmd(){ dirName=`dirname $1` [ -d ${dirPath}${dirName} ] || mkdir -p ${dirPath}${dirName} [ -f ${dirPath}${cmdPath} ] || cp $1 ${dirPath}${dirName} } cpLib(){ for i in `ldd $1 | grep -o "/[^[:space:]]\{1,\}"`;do dirLib=`dirname $i` [ -d ${dirPath}${dirLib} ] || mkdir -p ${dirPath}${dirLib} [ -f ${dirPath}$i ] || cp $i ${dirPath}${dirLib} done } while true;do read -p "Enter a command:" cmd if [ "$cmd" == 'quit' ];then echo "quit!" exit 0 fi clearcmd $cmd [ $? -eq 4 ] && continue cpCmd $cmdPath cpLib $cmdPath done
# mkdir /mnt/sysroot/etc/dropbear # dropbearkey -t rsa -s 1024 -f /mnt/sysroot/etc/dropbear/dropbear_rsa_host_key # dropbearkey -t dss -f /mnt/sysroot/etc/dropbear/dropbear_dss_host_key
# cp -d /lib64/libnss_files* /mnt/sysroot/lib64 # cp -d /usr/lib64/libnss3.so /mnt/sysroot/usr/lib64/ # cp -d /usr/lib64/libnss_files.so /mnt/sysroot/usr/lib64/ # cp /etc/nsswitch.conf /mnt/sysroot/etc/ # vim /mnt/sysroot/etc/nsswitch.conf 只保留以下幾項(xiàng)、其他的都不需要: passwd: files shadow: files group: files hosts: files dns 在用戶登錄時(shí)dropbear認(rèn)為用戶的默認(rèn)shell并不在/etc/shells下所在的用戶shell中的話、他是不允許登錄的、那我們就得給dropbear提供一個(gè)安全shell的配置文件了: # vim /etc/shells /bin/sh /bin/hush /bin/ash /sbin/nologin /bin/bash 要知道、dropbear啟動(dòng)時(shí)在/var/run/下會(huì)生成一個(gè)pid文件、而這個(gè)目錄我們還沒有創(chuàng)建、 # vim /mnt/sysroot/etc/fstab 加一行 devpts /dev/pts devpts defaults 0 0 再創(chuàng)建/dev/pts這個(gè)目錄: # mkdri /mnt/sysroot/etc/profile.d # cp /etc/profile.d/dropbear.sh /mnt/sysroot/etc/profile.d/ # mkdir /mnt/sysroot/dev/pts # sync
# yum -y install pcre-devel # tar xf nginx-1.4.2.tar.bz # cd nginx-1.4.2 # ./configure --prefix=/usr/local --conf-path=/etc/nginx/nginx.cnf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --user=nginx --group=nginx --without-pcre --without-http_rewrite_module --without-http_geo_module --without-http_uwsgi_module --without-http_fastcgi_module --without-http_scgi_module --without-http_memcached_module --prefix=/usr/local:指定第三方軟件安裝目錄 --conf-path=/etc/nginx/nginx.cnf:指定主配置文件的路徑 --error-log-path=/var/log/nginx/error.log:指定錯(cuò)誤日志存放路徑 --http-log-path=/var/log/nginx/access.log:指定訪問日志 --group=nginx:以nginx用戶身份運(yùn)行、反正不要以管理員的身份去運(yùn)行 --group=nginx:nginx用戶組 其他的選項(xiàng)都是nginx默認(rèn)選項(xiàng)、我們都去掉 # make # make install # useradd nginx # cd /usr/local/sbin # ./nginx # ss -tnl 查看80端口是否已經(jīng)處于監(jiān)聽狀態(tài) 接著移植nginx到目標(biāo)機(jī)上去、用上面的那個(gè)復(fù)制命令的腳本: 復(fù)制nginx下的配置文件到目標(biāo)機(jī)上、而啟動(dòng)nginx需要nginx用戶、所以用戶也得追加到passwd文件中去、而后再給nginx添加一個(gè)測試頁面就OK了: # cp /etc/nginx/ /mnt/sysroot/etc/ -r # grep "^nginx" /etc/passwd >> /mnt/sysroot/etc/passwd # grep "^nginx" /etc/group >> /mnt/sysroot/etc/group # grep "^nginx" /etc/shadow >> /mnt/sysroot/etc/shadow # mkdir /mnt/sysroot/usr/local/html # vim /usr/loca/html/index.html <h2>Wecome to Nginx</h2> <h3>This is MyLinux</h3> 給nginx提供一個(gè)服務(wù)腳本 #!/bin/sh # # nginx - this script starts and stops the nginx daemon # # chkconfig: - 85 15 # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ # proxy and IMAP/POP3 proxy server # processname: nginx # config: /etc/nginx/nginx.conf # config: /etc/sysconfig/nginx # pidfile: /var/run/nginx.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/local/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/etc/nginx/nginx.conf" [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx lockfile=/var/lock/subsys/nginx make_dirs() { # make required directories user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -` options=`$nginx -V 2>&1 | grep 'configure arguments:'` for opt in $options; do if [ `echo $opt | grep '.*-temp-path'` ]; then value=`echo $opt | cut -d "=" -f 2` if [ ! -d "$value" ]; then # echo "creating" $value mkdir -p $value && chown -R $user $value fi fi done } start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 make_dirs echo -n $"Starting $prog: " daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog -QUIT retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { configtest || return $? stop sleep 1 start } reload() { configtest || return $? echo -n $"Reloading $prog: " killproc $nginx -HUP RETVAL=$? echo } force_reload() { restart } configtest() { $nginx -t -c $NGINX_CONF_FILE } rh_status() { status $prog } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2 esac
# mkdir /mnt/sysroot/var/log/nginx # mkdir /mnt/sysroot/usr/local/logs # mkdir -pv /mnt/sysroot/var/lock/subsys # chmod +x /mnt/sysroot/var/log/nginx # chmod +x /mnt/sysroot/tmp/ # sync OK、我們啟動(dòng)定制的目標(biāo)系統(tǒng)、再啟動(dòng)dropbear和nginx、而服務(wù)也可以正常啟動(dòng)了、測試我們的nginx吧、如果服務(wù)腳本使用不了那就是里 面可以有一些依賴函數(shù)或一些命令沒有全都移植到目標(biāo)機(jī)上、不過不要緊、我們可以手動(dòng)啟動(dòng)服務(wù)器、這個(gè)問題都不大、最后測試完沒什么就poweroff關(guān)機(jī) 吧、如果nginx啟動(dòng)不了就重新把文件系統(tǒng)掛載為可讀寫就OK了:# mount -o remonut,rw / |
|