最近在自制裁剪一套比较小的Linux系统,现在将流程记录下来,顺便分享一下
自制的Linux系统大小不到500M,相比原先的4.5G,结果还是比较满意,如果再去除掉一些驱动、命令还可以更小
在自制Linux 系统,我们需要考虑的问题:
1.磁盘,分区
2.根文件系统
3.引导系统
4.内核
首先你得有一个可以运行的系统,不论是USB,虚拟机,还是真机;这里使用的Ubuntu 18.04.1
一、磁盘,分区
1.准备一块磁盘,安装在机器上,大小大于20G最好
2.进入Linux系统,初始化磁盘,进行分区,这里使用Gpt分区
1).获取新安装的磁盘
sudo fdisk -l | grep sd*
可以看到有一块没有初始化的硬盘,我这里是 /dev/sdb
2).初始化硬盘,我这里分6个区,我是为了兼容以前真机里面的一些设置,这里可以按自己的需求进行分区
sudo /dev/sdb
下面是fdisk工具的一些命令
g:使用gpt分区格式
n:新增一个分区
新增分区后,选择分区号,我这里默认
确定分区开始地址,默认即可
确定分区结束地址,例如 你需要分配20G空间给该分区,输入:+20G;前面的+号一定要有
分区出来的文件系统格式默认为ext4
t:修改分区文件格式
l:列出所有的文件系统格式
输入文件系统格式的编号
分配完所有分区以后记得保存
w:保存
Disk /dev/sdb: 111.8 GiB, 120034123776 bytes, 234441648 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 952A121F-25E2-C449-8ECF-6C40AC0623F4
Device Start End Sectors Size Type
/dev/sdb1 2048 4095 2048 1M BIOS boot
/dev/sdb2 4096 413695 409600 200M Linux filesystem
/dev/sdb3 413696 84299775 83886080 40G Linux filesystem
/dev/sdb4 84299776 178671615 94371840 45G Linux filesystem
/dev/sdb5 178671616 182865919 4194304 2G Linux swap
/dev/sdb6 182865920 234441610 51575691 24.6G Linux filesystem
3).格式化系统分区
格式化ext4分区
sudo mkfs.ext4 /dev/sdb2
sudo mkfs.ext4 /dev/sdb3
sudo mkfs.ext4 /dev/sdb4
sudo mkfs.ext4 /dev/sdb6
格式化swap分区
mkswap /dev/sdb2
查看UUID
sudo blkid
/dev/sdb1: PARTUUID="807358de-0814-2142-8cbf-8a1ddc60af59"
/dev/sdb2: UUID="43005813-2ac9-4d97-8e45-d2b798e328fe" TYPE="ext4" PARTUUID="a9098552-1d2d-8b43-a860-06a09499903b"
/dev/sdb3: UUID="0b3d6f52-4103-48be-b9fa-8fe500a0a0f5" TYPE="ext4" PARTUUID="43e1cb52-4029-1f47-883f-4abc8a9fb4d8"
/dev/sdb4: UUID="94934fc3-5c51-4338-8339-80e539e20b50" TYPE="ext4" PARTUUID="319fd72c-c97a-f540-915a-267cb3649a7a"
/dev/sdb5: UUID="26947552-a25c-49ff-9d22-5aac14365349" TYPE="swap" PARTUUID="68df19bb-2339-b241-8972-c05fb31fdd5c"
/dev/sdb6: UUID="08a96d35-b7d1-4fd6-bc2d-32912fd6d02e" TYPE="ext4" PARTUUID="d3d05ab4-0165-144f-8e7f-4307988e3dbf"
二、准备根文件系统
1.自己制作根文件
1). 创建sysroot、boot目录
sudo mkdir -pv {/mnt/boot, /mnt/sysroot}
/mnt/boot 用来盛放Linux内核启动相关文件
/mnt/sysroot 用来盛放Linux跟文件系统
2).创建copycmd.sh 用来拷贝一些必要的命令
#!/bin/bash
#
read -p "please input a excute cmd(eg:cat|bash|quit):" command
[ -a /mnt/sysroot ]||mkdir /mnt/sysroot &>/dev/null
cpdir () {
cmd=`which $command`
if [ -f /mnt/sysroot$cmd ];then
echo "the $cmd has been cp before"
else
local dir=`dirname $cmd`
mkdir -p /mnt/sysroot$dir
cp $cmd /mnt/sysroot$cmd
echo "cp $cmd finished"
fi
}
cplib () {
cmd=`which $command`
ldd $cmd |egrep -o "/lib64.* "|while read i;do
if [ ! -f /mnt/sysroot$i ];then
local dir=`dirname $i`
mkdir -p /mnt/sysroot$dir
cp $i /mnt/sysroot$i
echo "cp $i finished"
else
echo "$i has been cp before"
fi
done
ldd $cmd | awk -F ' ' '{print $1}'|while read i;do
if [ ! -f /mnt/sysroot$i ];then
local dir=`dirname $i`
mkdir -p /mnt/sysroot$dir
cp $i /mnt/sysroot$i
echo "cp $i finished"
else
echo "$i has been cp before"
fi
done
}
type $command&>/dev/null||{ echo the command is not exsit;exit 100; }
until [ $command == quit ];do
type $command&>/dev/null||{ echo the command is not exsit;exit 100; }
cpdir
cplib
read -p "please input new excute cmd(eg:cat|bash|quit):" command
cmd=`which --skip-alias $command`
done
拷贝命令如:bash,ls,cd,ifconfig,ping...
3).创建其它根下的文件夹,如:etc,dev 等
cd /mnt/sysroot
mkdir {etc,dev,proc,sys,boot,home,var,root,mnt,tmp,lib}
这里只是创建根文件系统的模型
2.使用debootstrap工具,制作根文件系统
1).安装debootstrap
sudo apt-get install debootstrap
2).创建sysroot、boot目录
sudo mkdir -pv {/mnt/boot, /mnt/sysroot}
3).下载最小化ubuntu 系统,需要设定平台架构--arch=amd64,以及确定版本bionic(18.04)
debootstrap --arch=amd64 bionic /mnt/sysroot https://mirrors.ustc.edu.cn/ubuntu
3.为根文件系统安装基本软件
1).绑定资源
sudo mount -o bind /dev /media/ubuntu/dev
sudo mount -o bind /dev/pts /media/ubuntu/dev/pts
sudo mount -o bind /etc /media/ubuntu/etc
sudo mount -o bind /proc /media/ubuntu/proc
sudo mount -o bind /sys /media/ubuntu/sys
2).chroot进入最小化系统
sudo chroot /mnt/sysroot
3).sudo 安装与passwd
apt-get update
apt-get install sudo
passwd
4).安装网络工具,以及dhcp服务
apt-get install net-tools dhcpcd5
5).退出最小化系统环境,解绑系统资源
exit
sudo umount -o bind /dev /media/ubuntu/dev
sudo umount -o bind /dev/pts /media/ubuntu/dev/pts
sudo umount -o bind /etc /media/ubuntu/etc
sudo umount -o bind /proc /media/ubuntu/proc
sudo umount -o bind /sys /media/ubuntu/sys
4.挂载磁盘,将文件系统写入磁盘
1).创建文件夹 /media/ubuntu
sudo mkdir -pv /media/ubuntu/boot
2).挂载磁盘
sudo mount /dev/sdb6 /media/ubuntu
sudo mount /dev/sdb2 /media/ubuntu/boot
这里在上面分区时就决定以第6块分区sdb6(20G大小)做为/分区,第2块分区sdb2 200M为boot分区
3).安装grub引导
sudo grub-install --root-directory=/media/ubuntu /dev/sdb
sudo update-grub
4).写入磁盘
sudo rsync -a /mnt/sysroot/* /media/ubuntu/
sudo rsync -a /boot/* /media/ubuntu/boot/
同步boot时 也可以使用自己编译的内核,或者替换其他内核
这里主要是使用rsync命令 实时同步刚刚创建的跟文件系统,以及将当前系统boot文件夹给同步
5).修改fstab
sudo vim /etc/fstab
将分区UUID以及分区挂载的文件 写入
# UNCONFIGURED FSTAB FOR BASE SYSTEM
UUID=08a96d35-b7d1-4fd6-bc2d-32912fd6d02e / ext4 errors=remount-ro 0 1
UUID=43005813-2ac9-4d97-8e45-d2b798e328fe /boot ext4 defaults 0 2
UUID=0b3d6f52-4103-48be-b9fa-8fe500a0a0f5 /data ext4 defaults 0 2
UUID=94934fc3-5c51-4338-8339-80e539e20b50 /database ext4 defaults 0 2
UUID=26947552-a25c-49ff-9d22-5aac14365349 none swap sw 0 1
6).修改grub配置文件/media/ubuntu/boot/grub/grub.cfg
因为当前文件的内是我们正在使用的这个系统的配置文件,系统的磁盘分区的UUID不一样,也有可能使用了不一样的内核;否则进不了系统
打开文件,
1).搜索search --no-floppy --fs-uuid --set ,这段代码后面跟了一串UUID指向了boot分区的UUID;将UUID替换为/media/ubuntu/boot挂载的分区的UUID;这里可以使用vim 全局替换
:%s/32669a74-c6cc-46ef-be17-7c822d0d698e/43005813-2ac9-4d97-8e45-d2b798e328fe/
32669a74-c6cc-46ef-be17-7c822d0d698e为当前使用的系统的boot分区的UUID
43005813-2ac9-4d97-8e45-d2b798e328fe为新的磁盘的boot分区的UUID
2).搜索linux /vmlinuz,这段代码后面跟了一串UUID指向了/分区的UUID;将UUID替换为/media/ubuntu/挂载的分区的UUID;这里可以使用vim 全局替换
:%s/a90160ab-b509-466a-be2c-9674877c8333/43005813-2ac9-4d97-8e45-d2b798e328fe/
a90160ab-b509-466a-be2c-9674877c8333 为当前使用的系统的/分区的UUID
08a96d35-b7d1-4fd6-bc2d-32912fd6d02e 为新的磁盘的/分区的UUID
3).系统内核镜像以及RAM disk映象
一个完整的grub启动菜单项
linux /vmlinuz-4.4.0-62-generic ...指的是内核镜像,这里可以修改为你需要使用内核镜像 后面跟是内核启动参数
initrd /initrd.img-4.4.0-62-generic 指的是RAM disk 临时根文件系统,这里面包含一些系统所需要的驱动模块
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-a90160ab-b509-466a-be2c-9674877c8333' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root 32669a74-c6cc-46ef-be17-7c822d0d698e
else
search --no-floppy --fs-uuid --set=root 32669a74-c6cc-46ef-be17-7c822d0d698e
fi
linux /vmlinuz-4.4.0-62-generic root=UUID=a90160ab-b509-466a-be2c-9674877c8333 ro net.ifnames=0 biosdevname=0
initrd /initrd.img-4.4.0-62-generic
}
4).修改最小化系统的休眠后恢复系统休眠前的状态,就是修改内核脚本/scripts/local-premount/写的脚本 resume脚本的配置文件件/etc/initramfs-tools/conf.d/resume
RESUME=UUID=767d6d7f-74b8-4d48-854e-492fb0fc8dcd
这里UUID指向新的磁盘的swap分区的UUID,不要写错了,不然启动会有问题,可见我上一篇文章Llinux内核启动时卡在Scanning for Btrfs filesystems
到这里,就已经完了,这上面的每一步都非常重要 不能缺少;相较于制作跟文件系统两种方法,第一种与第二种的优缺点:
第一种自己制作根文件系统:
优点:占用空间小,可以最小化系统使用的服务,消耗资源少
缺点:后期需要配置很多很多东西,相对来说比较麻烦
第二种使用debootstrap:
优点:后期配置较少
缺点:相较第一种,占用空间、性能消耗等都要大一点
建议使用第二种,简单
最后重启,进入bios,最小化系统的磁盘作为启动盘启动;如果以上配置都正确,就可以成功启动该系统,如果不能启动,最多的问题就在grub上,好好看看自己的配置文件