出处:http://xuqimin.blog.51cto.com/3832456/1367760
l 要求:
裁剪一个装载有网卡驱动可以上网并且使用到init的一个小系统
l 准备;
虚拟机,centos6.4
l 步骤;
一、在宿主机上添加一块硬盘,并为其安装grub
1. 在宿主机上添加一块硬盘,这里添加的是sde这块硬盘。
2. 使用fdisk为sde分两个区,sde1 (100M) sde2(2G)
3. 创建目录/mnt/boot /mnt/sysroot
1
|
mkdir
-pv
/mnt/
{boot,sysroot}
|
4. 将/dev/sde1挂载到/mnt/boot ,/dev/sde2挂载到/mnt/sysroot
1
2
3
4
5
6
7
|
mount
/dev/sde1
/mnt/boot/
mount
/dev/sde2
/mnt/sysroot/
[root@station57 mnt]
# mount
......
......
/dev/sde1
on
/mnt/boot
type
ext4 (rw)
/dev/sde2
on
/mnt/sysroot
type
ext4 (rw)
|
5. 当剪裁成功后sde2分区会当作新系统的跟分区,所以要给你sde2这个分区也就是/mnt/sysroot 这个目录创建linux系统常用的几个目录
1
|
[root@station57 sysroot]
# mkdir -pv mnt proc root home cat sys lib lib64 dev media sbin tmp var
|
6. 安装gurb
注意次处的“--root-directory=/mnt”选项,sde1是挂载在/mnt/boot上边的,不要写成--root-directory=/mnt/boot 了。
1
2
3
4
5
6
7
8
9
10
11
|
[root@station57 mnt]
# grub-install --root-directory=/mnt /dev/sde
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
(hd2)
/dev/sdc
(hd3)
/dev/sdd
(hd4)
/dev/sde
|
7. 因为我的宿主机上有五块硬盘,所以此处列出了hd1--hd4.。我们的sde对应的硬盘是hd4,但是这个编号4仅仅对次主机有效,换到一个单独的主机上的时候就是hd0了。所以后边出来了(hd0,0)这样的硬盘标号。第一个0代表硬盘编号,第二个表示分区
8. 此时硬盘sde的grub就算安装成功了,我们看一下里边的内容
1
2
3
4
5
|
[root@station57 mnt]
# ls /mnt/boot/grub/
device.map iso9660_stage1_5 stage1 xfs_stage1_5
e2fs_stage1_5 jfs_stage1_5 stage2
fat_stage1_5 minix_stage1_5 ufs2_stage1_5
ffs_stage1_5 reiserfs_stage1_5 vstafs_stage1_5
|
Grub有3个stage,
1st stage: 位于MBR中,为了引导2nd stage
1.5 stage: 位于boot基本磁盘分区中,为识别内核文件所在的文件系统提供文件系统识别扩展
2nd stage: 位于boot基本磁盘分区中,GRUB的引导程序
二、复制内核vmlinuz和内核加载部分硬件所依赖的initramfs
1
2
|
1. [root@station57 mnt]
# cp /boot/vmlinuz-2.6.32-358.el6.x86_64 /mnt/boot/
2. [root@station57 mnt]
# cp /boot/initramfs-2.6.32-358.el6.x86_64.img /mnt/boot/
|
三、添加gurb的配置文件
grub安装完成了如果不添加配置文件,那么每次启动都要手动写内核文件vmlinuz-和驱动相关的initramfs两个文件的路径,而且还要定义跟的位置,很不方便,于是就要用到gurb的配置文件grub.conf
1
2
3
4
5
6
7
|
[root@station57 mnt]
# vim /mnt/boot/grub/grub.conf
default=0
timeout=5
title CentOS (author:xuqimin)
root (hd0,0)
kernel
/vmlinuz-2
.6.32-358.el6.x86_64 ro selinux=0 root=
/dev/sda2
init=
/bin/bash
initrd
/initramfs-2
.6.32-358.el6.x86_64.img
|
在grub中,硬盘以hd开头紧跟一个数字做各磁盘设备的标记,从0开始编号
Part表示方式:代表分区,从0开始编号
配置文件代表的意义
1、default=#: 指定默认启动的内核或OS;
2、timeout=#: 等待用户选择要启动的内核或OS的时长,单位为秒;
3、Kernel 后边给的参数为传递给内核的参数
4、Ro 表示以只读的方式挂载
5、Seliunx=0 表示不启用selinux ,因我们这里的小系统只要内核和几个简单的命令,启动不了selinux ,而gurb默认是开启selinux的,这样我们开机的时候会出现问题而无法启动系统
6、Root=/dev/sda2 表示等系统系统的时候会以sda2 ,也就是刚刚我们挂载的sde2来当作系统的根目录。
四、编写复制命令及其对应的库的脚本,并完成命令迁移
gurb和内核文件及驱动文件都已就绪,但是系统还只是一个只有内核的空壳而已,显然我们还不能用它做任何事情。因此我们就需要把linux中常用到的命令复制到我们制作的小系统中,以让它工作起来。
我们知道命令是由二进制文件,极其依赖的库文件,再加上一些帮助文档组成的。而且一个命令的库文件不知只有一个。所以我们单单手动复制起来的话势必会很麻烦。所以此时就需要把我们前面学到的脚本知识发挥一下,用shell脚本实习命令的复制,迁移。下边是我前几天做的复制命令的脚本。
(脚本可能有不完善的地方,也可能在大神眼中很臃肿,不喜勿喷)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#!/bin/bash
2
3
function
EnterCommand {
4
read
-p
"Enter a command:"
command
5
while
true
;
do
6 [[
"$command"
==
"quit"
]] &&
exit
2
7
if
which
$
command
&>
/dev/null
;
then
8
break
9
else
10
echo
-e
"\n\033[31mno such command,please try agiain.and quit to quit:\n\033[0m"
11
read
-p
"Enter a command:"
command
12
fi
13
done
14 }
15
16
17
function
bincp {
18 commandDir=`
which
--skip-
alias
$
command
`
19 distintion=
"/mnt/sysroot$commandDir"
20
if
[ -e $distintion ];
then
21
echo
"bin of $command is already exist."
22
else
23 [ -d
/mnt/sysroot
`
dirname
$commandDir` ] ||
mkdir
-p
/mnt/sysroot
`
dirname
$commandDir`
24
cp
$commandDir
/mnt/sysroot
`
dirname
$commandDir` &&
echo
"the bin cp ok.."
||
echo
"cp bin error"
25
fi
26 }
27
28
29
function
Libcp {
30 commandLib=`ldd $commandDir |
grep
-o
"/lib.*[[:space:]]"
`
31
32
for
i
in
$commandLib ;
do
33 distintionlib=
"/mnt/sysroot$i"
34
if
[ -e $distintionlib ];
then
5
echo
"$i is exist."
36
37
else
38
39 [ -d
/mnt/sysroot
`
dirname
$i` ] ||
mkdir
-p
/mnt/sysroot
`
dirname
$i`
40
cp
$i
/mnt/sysroot
`
dirname
$i` &&
echo
"lib co ok.."
||
echo
"cp lib erro "
41
fi
42
done
43 }
44
45
46
47
48 EnterCommand
49
50
while
true
;
do
51 bincp
52 Libcp
53 EnterCommand
54
done
|
执行这个脚本,分别将bash,ls,cd ,vi ,cat,tree,fdisk,mv,touch,这些常用的命令复制到/mnt/sysroot中对用的路径下。
此时将sde这块硬盘放到一个其他的电脑上就已经可以启动了,只不过有点简陋。只能在bash shell中执行cp过去的几个小命令。也没有网络功能,如果需要使用网络功能,就需要通过下边的几个布置继续迁移网卡驱动模块了。
新建虚拟机,把sde这块硬盘放到新虚拟机中当启动盘。(注意:使用sde这看硬盘的时候要讲原宿主机挂载)
无图无真像,贴个图给大家看看吧。
五、迁移e1000 网卡驱动内核模块
系统要想上网得需要有网卡驱动。而linux中网卡驱动不是在内核中自带的,而是以模块的方式在内核中转载的,所以我们要想让我们迁移的小linu能够有网络功能还必须为其装载网卡驱动模块
下边列出关于管理内核模块所用到的几个命令,当然我们在做下边操作之前还需要通过上边的哪个cp二进制的脚本来讲几个命令cp过去,另外别忘了复制ifconfig,ping这些我们等会可能会用到命令了。
1. 查找我们需要的模块在宿主机上的位置
Lsmod:查看内核转载的模块
Lspci:查看pci插口相关信息
Modproc:转载相应模块
Modproc -r :卸载模块
Insmod:装载模块
Rmmod:卸载模块
有了这些命令接下来让我们找找网卡模块在哪吧。
1
2
3
4
5
6
7
8
9
10
11
|
[root@station57 sysroot]
# lsmod
Module Size Used by
autofs4 26513 3
8021q 25317 0
ipv6 321422 96
e1000 170646 0
sg 29350 0
......
......
dm_log 9930 2 dm_mirror,dm_region_hash
dm_mod 82839 14 dm_mirror,dm_log
|
上边的e1000就是我们要找的网卡模块,你是不是该问那还是没有解决问题呀,e1000在哪呢。我们别忘了还有一个modinfo命令呢。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[root@station57 sysroot]
# modinfo e1000
filename:
/lib/modules/2
.6.32-358.el6.x86_64
/kernel/drivers/net/e1000/e1000
.ko
version: 7.3.21-k8-NAPI
license: GPL
description: Intel(R) PRO
/1000
Network Driver
author: Intel Corporation, <[email protected]>
srcversion: 1D4F1E82BB99EA36D320B1B
alias
: pci:v00008086d00001000sv*sd*
bc
*sc*i*
........
depends:
vermagic: 2.6.32-358.el6.x86_64 SMP mod_unload modversions
parm: TxDescriptors:Number of transmit descriptors (array of int)
.....
......
|
好大一串数据呀,反正大多数我是不懂干嘛的。暂时先不关心其他内的内容吧,我们只关心这个路径在哪、还有下边的depends是模块依赖的别的模块。这里的e1000不依赖别的模块。
filename: /lib/modules/2.6.32-358.el6.x86_64/kernel/drivers/net/e1000/e1000.ko
2. 复制该模块到我们的小型linux中安装
1
2
3
|
[root@station57 sysroot]
# cp /lib/modules/2.6.32-358.el6.x86_64/kernel/drivers/net/e1000/e1000.ko /mnt/sysroot/lib/modules/
[root@station57 sysroot]
# ls /mnt/sysroot/lib/modules/
e1000.ko
|
3. 挂起宿主机,开启目标主机,并用刚刚使用的sde来做启动盘开启主机。
使用insmod 转载模块,然后就可以使用ifconfig配置ip地址了。这样我们的带有网络功能的小linux系统就做好了。
l 使用init自启动服务脚本完成系统初始化
我们的带有网络功能的小系统已经做好,但是你有没有发现每次重启后我们的网络模块都要重启装载,而且ip地址也要重新配置。这真是一件头疼的事情,有没有一个脚本可以自动化的帮我们完成这些模块的自动装载呢,当然有,init就是为了完成这个任务,但是init这个功能太多,需要依赖的东西也太多,我们也不需要。那么就让我们来自己写一个脚本来代替init完成我们的小系统初始化吧。
1
2
3
4
5
6
7
8
9
|
[root@station57 mnt]
# vim /mnt/sysroot/sbin/init
1
#!/bin/bash
2
#
3
echo
-e
"\t\033[31;5mI am a simple Linux, but I'll grow up soon\033[0m"
4
5 insmod
/lib/modules/e1000
.ko &&
echo
-e
"Moduless e1000 loding\033[60G\033[32m[ ok ]\033[0m "
||
echo
"Moduless e1000 loging error"
6
ifconfig
lo 127.0.0.0
/16
&&
echo
-e
"The ip lo add ...\033[60G\033[32m[ ok ]\033[0m "
||
echo
"ip of lo add error"
7
ifconfig
eth0 172.16.20.11
/16
&&
echo
-e
"The ip eth0 add ...\033[60G\033[32m[ ok ]\033[0m "
||
echo
"ip of eth0 add error"
8
/bin/bash
:::::别忘了最后启动shel呀!
|
这个脚本完成了对模块e1000的自动挂载,并且自动配置ip的功能。
不过需要注意的是,我们如果让他开启生效,需要在grub.conf中定义init指向次脚本路径。