一、开场白:
今天我来制作一个简单的linux系统,但在制作之前我们先了解一下系统的启动流程吧。
linux系统的启动过程大致经过一下几个步骤:
1、POST:开机自检ROM和RAM。
2、BIOS(boot sequence):根据BIOS中的启动次序来引导操作系统。
3、GRUB:加载GRUB上的bootloader。
4、kernel:启动内核。
5、initrd:initrd借助内核启动根文件系统。
6、init:启动用户空间的进程并进行系统初始化等工作。
详情见下图:
二、准备环境:
1、开一个linux宿主机,并添加一块5G的scsi硬盘,取个名叫mini linux:
2、准备一个目标机,该目标机的硬盘选择在宿主机上添加的新硬盘,因为我们要在宿主机上的5G新硬盘安装grub,并创建根文件系统,让grub引导并启动根文件系统。
三、正式步骤:
1、在宿主机上新添加的硬盘上新建2个分区,/dev/sdb1做boot分区,/dev/sdb2作为根分区:
[root@station156 ~]# fdisk -l /dev/sdb
Disk /dev/sdb: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x87fe92a9
Device Boot Start End Blocks Id System
/dev/sdb1 1 26 208813+ 83 Linux
/dev/sdb2 27 288 2104515 83 Linux
2、格式化2个新分区:
mke2fs -t ext4 /dev/sdb1
mke2fs -t ext4 /dev/sdb2
3、在/mnt目录下新建2个目录boot和sysroot:
[root@station156 ~]# mkdir -pv /mnt/{boot,sysroot}
mkdir: created directory `/mnt/boot'
mkdir: created directory `/mnt/sysroot'
4、将/dev/sdb1挂载到/mnt/boot,将/dev/sdb2挂载到/mnt/sysroot:
[root@station156 ~]# mount /dev/sdb1 /mnt/boot/
[root@station156 ~]# mount /dev/sdb2 /mnt/sysroot/
[root@station156 ~]# mount
/dev/mapper/vg0-root on / type ext4 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
/dev/sda1 on /boot type ext4 (rw)
/dev/mapper/vg0-usr on /usr type ext4 (rw)
/dev/mapper/vg0-var on /var type ext4 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
/dev/sdb1 on /mnt/boot type ext4 (rw)
/dev/sdb2 on /mnt/sysroot type ext4 (rw)
5、写一个脚本,以便将来移植宿主机上的二进制程序及其依赖的库文件到目标机的根文件系统上去:
[root@station156 ~]# cat copy.sh
#!/bin/bash
target=/mnt/sysroot
clearcmd() {
if which $cmd &> /dev/null;then
cmdpath=`which --skip-alias $cmd`
else
echo "no such command!"
return 8
fi
}
cmdcopy() {
cmddir=`dirname $1`
[ -d ${target}${cmddir} ] || mkdir -p ${target}${cmddir}
[ -f ${target}${1} ] || cp $1 ${target}${cmddir}
}
libcopy() {
for lib in `ldd $1 | grep -o "/[^[:space:]]\{1,\}"`;do
libdir=`dirname $lib`
[ -d ${target}${libdir} ] || mkdir -p ${target}${libdir}
[ -f ${target}${lib} ] || cp $lib ${target}${libdir}
done
}
while true;do
read -p "enter a command:" cmd
if [ "$cmd" == "quit" ];then
echo "quit"
exit 0
fi
clearcmd $cmd
[ $? -eq 8 ] && continue
cmdcopy $cmdpath
libcopy $cmdpath
done
脚本解释:首先提示用户输入一个二进制程序(cmd),以bash为例,如果用户输入的是quit,则正常退出,如果用户输入的命令系统没有,就提示用户“no such command!”,然后继续循环提示用户输入命令,直到正确。如果用户输入的二进制程序系统有,则显示此命令的绝对路径,如bash的路径为:/bin/bash,如果/mnt/sysroot/没有bin目录,则创建,创建之后再看/mnt/sysroot/bin/下有没有bash程序,如果没有就复制bash到/mnt/sysroot/bin下面。如bash的库文件为/lib64/libtinfo.so.5,/lib64/libdl.so.2,/lib64/libc.so.6 ,先查看/mnt/sysroot下面有没有lib64目录,如果没有就创建,再看/mnt/sysroot/lib64下面有没有libtinfo.so.5、libdl.so.2、libc.so.6库文件,如果没有就把它们复制到/mnt/sysroot/lib64下面去。(解释的可能不太好,敬请谅解)
6、安装grub至目标磁盘:
[root@station156 ~]# grub-install --root-directory=/mnt /dev/sdb
Probing devices to guess BIOS drives. This may take a long time.
Installation finished. No error reported.
This is the contents of the device map /mnt/boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.
(fd0) /dev/fd0
(hd0) /dev/sda
(hd1) /dev/sdb
说明:由于boot的上一级目录是mnt,于是就指定grub的root目录为/mnt,并把grub安装到新添的5G硬盘上。
7、复制内核文件和initrd文件到/mnt/boot/目录下面去:
[root@station156 ~]# cp /boot/vmlinuz-2.6.32-358.el6.x86_64 /mnt/boot/vmlinuz
[root@station156 ~]# cp /boot/initramfs-2.6.32-358.el6.x86_64.img /mnt/boot/initramfs.img
8、为grub提供配置文件:
[root@station156 ~]# cat /mnt/boot/grub/grub.conf
default=0
timeout=5
title mini linux
root (hd0,0)
kernel /vmlinuz ro root=/dev/sda2 quiet selinux=0 init=/sbin/init
initrd /initramfs.img
说明:default的值为0表明从第一个内核或系统启动;timeout指定进入GRUB菜单的超时时间;title指定系统名称为mini linux;root (hd0,0)表明从第一块磁盘的第一个分区启动(/dev/sdb1),5G硬盘将来作为目标机的硬盘;kernel后面指定内核为/vmlinuz,内核是在一个独立的基本文件系统中;ro指定内核为只读;root=/dev/sda2指定内核挂载在根文件系统/dev/sda2,由于在宿主机上的5G新硬盘的根分区是/dev/sdb2,从宿主机拿掉放到目标机上后根文件分区应该是叫/dev/sda2;quiet指以静默模式执行初始化;selinux=0指关闭selinux;init=/sbin/init指启动用户空间的进程init,并执行/sbin/init中定义的操作。
9、创建目标主机的根文件系统:[root@station156 ~]# mkdir -pv /mnt/sysroot/{etc/rc.d, usr, var, proc, sys, dev, lib, lib64, bin, sbin, boot, srv, mnt, media, home, root}
10、在目标机的根文件系统上的库目录(lib)下面新建目录modules(用来放模块),并把宿主机上的网卡模块复制到/mnt/sysroot/lib/modules中去:[root@station156 ~]# mkdir -pv /mnt/sysroot/lib/modules
mkdir: created directory `/mnt/sysroot/lib'
mkdir: created directory `/mnt/sysroot/lib/modules'
[root@station156 ~]# cp /lib/modules/2.6.32-358.el6.x86_64/kernel/drivers/net/e1000/e1000.ko /mnt/sysroot/lib/modules/
11、执行脚本copy.sh,复制一些二进制程序及库文件到目标机上的根文件系统中去:
[root@station156 ~]# bash copy.sh
enter a command:bash
enter a command:ifconfig
enter a command:insmod
enter a command:rmmod
enter a command:ping
enter a command:mkdir
enter a command:touch
enter a command:ls
enter a command:cat
enter a command:mount
enter a command:umount
enter a command:chmod
enter a command:quit
quit
12、在目标机的根文件系统上新建用户空间的init文件,并定义init在初始化时执行的操作,给init以执行权限:
[root@station156 sbin]# chmod +x init
[root@station156 sbin]# ll init
-rwxr-xr-x 1 root root 339 Mar 5 18:45 init
注意:如果不给目标机的根文件系统的sbin目录下的init程序以执行权限,就无法执行初始化时的装载网卡模块、自动挂载根文件系统等操作,甚至无法启动bash。
13、建立bash的软连接:
[root@station156 bin]# ln -sv bash sh
`sh' -> `bash'
14、将所有信息同步到/dev/sdb上去:
[root@station156 ~]# sync
[root@station156 ~]# sync
15、新建一个虚拟机为目标机,硬盘选择在宿主机上新添的5G硬盘,名称为mini linux:
三、验证mini linux系统:
打开目标机,显示欢迎信息以及网卡模块装载成功,IP地址已自动配置完成,并能够ping通其它主机:
四、经验教训:
本人在进行该实验的操作时因为一个权限的问题(红体字)导致mini linux报错而无法启动,这就验证了一句话:一着不慎,满盘皆输。所以,大家不要像我一样粗心大意哦!