最近在自制裁剪一套比较小的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,不要写错了,不然启动会有问题

到这里,就已经完了,这上面的每一步都非常重要 不能缺少;相较于制作跟文件系统两种方法,第一种与第二种的优缺点:

第一种自己制作根文件系统:

优点:占用空间小,可以最小化系统使用的服务,消耗资源少

缺点:后期需要配置很多很多东西,相对来说比较麻烦

第二种使用debootstrap:

优点:后期配置较少

缺点:相较第一种,占用空间、性能消耗等都要大一点

建议使用第二种,简单

 

最后重启,进入bios,最小化系统的磁盘作为启动盘启动;如果以上配置都正确,就可以成功启动该系统,如果不能启动,最多的问题就在grub上,好好看看自己的配置文件