Linux系统裁剪笔记
1.什么裁剪?
本篇文章的主要目的是让笔者和读者更深的认识Linux系统的运作方式,大致内容就是把Linux拆开自己一个个组件来组装,然后完成一个微型的Linux系统,从而达到系统缩减,订制特殊系统。
2.原理
大家都知道,操作系统的启动流程是(主要是Linux):POST—>BIOS—>MBR(grub)—kernel-->initrd-->sbin/init,
POST,BIOS都不是我们管的,所以这里我们从MBR开始,Linux的系统引导先主要是用的grub这个软件,grub引导系统了,然后启动内核,内核调用initrd来实现最基本的操作系统,
3.实验 (所有操作均在虚拟机上实现,且定义硬盘时选IDE)
环境:1).在宿主机上安装一台Redhat5.4,/dev/sda上安装操作系统;
2).在宿主机上新建一个新硬盘:/dev/hda,且分区为512M的hda1,1G的hda2;
3).另建立一台测试虚拟机,将原有的硬盘删除,再将硬盘/dev/hda的新增到该测试虚拟机;
1、首先我们得创建一个新的磁盘,来保存我们的grub和内核等关键程序(直接在虚拟机上添加新的磁盘)
分两个区,分别是512M的hda1主盘,和1G的sdb2主盘。
[[email protected] ~]# fdisk -l 查看硬盘分区信息
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: 0x57e43c23
Device Boot Start End Blocks Id System
/dev/hda1 1 63 506016 83 Linux
/dev/hda2 64 195 1060290 83 Linux
/dev/hda3 196 327 1060290 82 Linux swap / Solaris
[[email protected] mnt]# mke2fs -j /dev/hda1 把分区/dev/hda1格式化成ext3文件系统类型
[[email protected] mnt]# mke2fs -j /dev/hda2 把分区/dev/hda2格式化成ext3文件系统类型
[[email protected] ~]# mkdir /mnt/{boot,sysroot} -pv 在当前系统中新建2个目录/mnt/boot /mnt/sysroot/
[[email protected] ~]# ls /mnt
boot lost+found sysroot
[[email protected] mnt]# mount /dev/hda1 /mnt/boot/ 把分区/dev/hda1挂载到/mnt/boot目录
[[email protected] mnt]# mount /dev/hda2 /mnt/sysroot/ 把分区/dev/hda2挂载到/mnt/sysroot目录
[[email protected] mnt]# mount 查看挂载的分区
...
/dev/hda1 on /mnt/boot type ext3(rw) 已挂载成功
/dev/hda2 on /mnt/sysroot type ext3 (rw) 已挂载成功
[[email protected] mnt]# ls boot/ #验证挂载是否成功
lost+found
[[email protected] mnt]# ls sysroot/
lost+found
2、启动系统的时候识别硬盘后要有引导程序,系统通过MBR可查找到/dev/sdb中的/mnt
[[email protected] mnt]# grub-install --root-directory=/mnt /dev/sdb 安装grub文件到/mnt目录
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/hda
(hd1) /dev/sda
(hd2) /dev/sdb
(hd3) /dev/sdc
[[email protected] mnt]# ls /mnt/boot/ #grub已成功生成
grub lost+found
3、有了引导程序就需要有我们的内核了,没有内核怎么启动啊,但是内核的启动又要依赖initrd,所以我们要建立/mnt/boot/vmlinuz,/mnt/boot/initrd.gz,/mnt/boot/grub/grub.conf
3.1、 复制内核文件vmlinuz
[[email protected] mnt]# cp /boot/vmlinuz-2.6.18-164.el5 /mnt/boot/vmlinuz
3.2、 手动展开文件2:initrd文件
方法一:
[[email protected] mnt]# cp /boot/initrd-2.6.18-164.el5.img /root 复制initrd文件到/root目录
[[email protected] mnt]# file /root/initrd-2.6.18-164.el5.img 查看该文件类型为gzip压缩格式
/boot/initrd-2.6.18-164.el5.img: gzip compressed data, from Unix, last modified: Thu Apr 17 11:43:57 2014, max compression
[[email protected] ~]# mv initrd-2.6.18-164.el5.img initrd-2.6.18-164.el5.img.gz 重命名为.gz格式
[[email protected] ~]# gzip -d initrd-2.6.18-164.el5.img.gz 解压该文件,gunzip=gzip -d
[[email protected] ~]# file initrd-2.6.18-164.el5.img 再次查看文件格式变为ASCII类型
initrd-2.6.18-164.el5.img: ASCII cpio archive (SVR4 with no CRC)
[[email protected] ~]# mkdir dirinit 创建一个空目录dirinit
[[email protected] ~]# cd dirinit/ 进入dirinit目录
[[email protected] dirinit]# cpio -id < ../initrd-2.6.18-164.el5.img 提取initrd文件中的内容到该目录中
13832 blocks
[[email protected] dirinit]# ls 查看是否提取成功
bin dev etc init lib proc sbin sys sysroot
[[email protected] dirinit]#
*
方法二:(一般用此方法)
[[email protected] ~]# mkdir testiso #创建空目录
[[email protected] ~]# cd testiso
[[email protected] testiso]# ls
[[email protected] testiso]# zcat /boot/initrd-2.6.18-164.el5.img | cpio -id
13832 blocks
[[email protected] testiso]# ls
bin dev etc init lib proc sbin sys sysroot
3.3、修改INIT文件中的启动分区,再打包成initrd.gz
[[email protected] testiso]# file init 查看init文件类型
init: a /bin/hush script text executable
[[email protected] testiso]# vim init 编辑init文件
#resume /dev/VolGroup00/LogVol01 #禁用swap分区
或#resume LABEL=SWAP-sda9 #禁用swap分区
mkrootdev -t ext3 -o defaults,ro /dev/hda2 #/dev/hda1为BOOT分区 #红色部分原为:sda5 或 /dev/VolGroup00/LogVol00 需改为/dev/hda2根目录分区
[[email protected] testiso]# find . | cpio -H newc --quiet -o | gzip -9 > /mnt/boot/initrd.gz
[[email protected] boot]# ls -lh
total 7.1M
drwxr-xr-x 2 root root 1.0K Nov 21 09:02 grub
-rw-r--r-- 1 root root 2.6M Nov 21 10:13 initrd.gz #init文件中改为/dev/sda2
drwx------ 2 root root 12K Nov 21 08:54 lost+found
-rw-r--r-- 1 root root 1.9M Nov 21 09:16 vmlinuz
3.4、 接下来要配置grub文件,不然系统怎么找到你的硬件,故新建grub.conf文件
[[email protected] boot]# vim /mnt/boot/grub/grub.conf
default=0
timeout=5
title Test Linux 5.4 (Test)
root (hd0,0)
kernel /vmlinuz
initrd /initrd.gz
4、 这样一个简单的操作系统的雏形就做好了,但是OS的操作依赖于shell,所以我们得手动复制bash、bash依赖的库文件,可写程式(附件bincopy.sh)自动复制。
[[email protected] sysroot]# mkdir -pv proc sys dev etc/rc.d lib lib64 bin sbin boot home var usr/{bin,sbin} root tmp 在该目录下新建proc sys dev etc/rc.d lib bin sbin boot home var usr/{bin,sbin} root tmp lib64(64位系统)等目录
[[email protected] sysroot]# cp /sbin/init /mnt/sysroot/sbin/
[[email protected] sysroot]# cp /bin/bash /mnt/sysroot/bin/
[[email protected] sysroot]# cp /sbin/init /mnt/sysroot/sbin/
[[email protected] sysroot]# cp /bin/bash /mnt/bin/
[[email protected] sysroot]# ldd /sbin/init
libsepol.so.1 => /lib64/libsepol.so.1 (0x0000003941c00000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003942000000)
libc.so.6 => /lib64/libc.so.6 (0x0000003940400000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003940c00000)
/lib64/ld-linux-x86-64.so.2 (0x0000003940000000)
[[email protected] sysroot]# cp /lib64/libsepol.so.1 /mnt/sysroot/lib64/ #复制相关库文件
[[email protected] sysroot]# cp /lib64/libselinux.so.1 /mnt/sysroot/lib64/
[[email protected] sysroot]# cp /lib64/libc.so.6 /mnt/sysroot/lib64/
[[email protected] sysroot]# cp /lib64/libdl.so.2 /mnt/sysroot/lib64/
[[email protected] sysroot]# cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/
[[email protected] sysroot]# ldd /bin/bash
libtermcap.so.2 => /lib64/libtermcap.so.2 (0x0000003943000000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003940c00000) 上面已经复制过,此处无需再复制
libc.so.6 => /lib64/libc.so.6 (0x0000003940400000) 上面已经复制过,此处无需再复制 /lib64/ld-linux-x86-64.so.2 (0x0000003940000000) 上面已经复制过,此处无需再复制
[[email protected] sysroot]# cp /lib64/libtermcap.so.2 /mnt/sysroot/lib64/
[[email protected] sysroot]# chroot /mnt/sysroot/ #切换根目录
bash-3.2# pwd
/
bash-4.1# ls
bash: ls: command not found
bash-4.1# exit
exit
[[email protected] sysroot]# sync 把数据同步到硬盘
[[email protected] sysroot]# cd /mnt/sysroot/
[[email protected] sysroot]# pwd
/mnt/sysroot
[[email protected] sysroot]# ls
bin boot dev etc home lib lib64 lost+found proc root sbin sys tmp usr var
5、 好了!系统到这里就差不多了,不过我们还得修修,大家可以看到,我们的init=/bin/bash,这时候就会有同学问了,有没搞错,Linux系统化初始化不都是调用/sbin/init的么,你怎么调用了/bin/bash,没错,其实这里指向什么就调什么,那我们现在重新让他指向/etc/rc.d/rc.sysinit。
[[email protected] sysroot]# vim etc/inittab 编辑inittab并保存
[[email protected] sysroot]# cat etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/rc.sysinit
[[email protected] sysroot]# vim etc/rc.d/rc.sysinit 编辑rc.sysinit并保存
[[email protected] sysroot]# cat etc/rc.d/rc.sysinit
#!/bin/bash
#
echo -e "\t Welcome to \033[32mDongen CentOS6.5\033[0m Linux"
/bin/bash
[[email protected] sysroot]# chmod +x etc/rc.d/rc.sysinit
[[email protected] sysroot]# sync 把数据同步到硬盘
[[email protected] sysroot]# sync 把数据同步到硬盘
[[email protected] sysroot]# sync 把数据同步到硬盘
[[email protected] sysroot]# sync 把数据同步到硬盘
[[email protected] sysroot]# sync 把数据同步到硬盘 多执行几次sync,以免没有同步成功
3.6.如下图,执行成功了
好了,整个系统安装完成了!
附1:自动复制相关库文件
#!/bin/bash
# bincopy.sh
DEST=/mnt/sysroot
libcp() { #该函数接收一个库文件路径
LIBPATH=${1%/*} #红色部分将/lib/libc.so.6切割成/lib/
[ ! -d $DEST$LIBPATH ] && mkdir -p $DEST$LIBPATH #路径是否存在
[ ! -e $DEST${1} ] && cp $1 $DEST$LIBPATH && echo "copy lib $1 finished."#库文件是否存在
}
bincp() { #该函数接收一个命令对应的地址,如:/bin/ls
CMDPATH=${1%/*} #红色部分将/bin/ls切割成/bin/
[ ! -d $DEST$CMDPATH ] && mkdir -p $DEST$CMDPATH
[ ! -e $DEST${1} ] && cp $1 $DEST$CMDPATH
for LIB in `ldd $1 | grep -o "/.*lib\(64\)\{0,1\}/[^[:space:]]\{1,\}"`; do
libcp $LIB # /.*lib绿色为:/开始,中间任意字符,接着lib
done # \(64\)\{0,1\}红色为:64出现0或1次
} # [^[:space:]]\{1,\}绿色为:空格开关且至少出现一次
read -p "Your command: " CMD
until [ $CMD == ‘q‘ ]; do
! which $CMD&> /dev/null && echo "Wrong command" && read-p "Input again:" CMD && continue
COMMAND=`which $CMD |grep -v "^alias" |grep -o "[^[:space:]]\{1,\}"`#以alias开头的行不显示
bincp $COMMAND
echo"copy $COMMAND finished."
read -p"Continue: " CMD
done