22 Linux高级篇-定制自己的Linux系统

news2024/11/30 12:31:53

22 Linux高级篇-定制自己的Linux系统

文章目录

  • 22 Linux高级篇-定制自己的Linux系统
    • 22.1 Linux7启动流程介绍
      • 22.1.1 Linux7启动流程
      • 22.1.3 systemd概述
    • 22.2 *制作min-linux思路分析
    • 22.3 操作步骤
      • 步骤1:创建新磁盘
      • 步骤2:制作启动盘
      • 步骤3:创建min-linux虚拟机
      • 步骤4(选做):添加额外的指令

  • 学习视频来自于B站【小白入门 通俗易懂】2021韩顺平 一周学会Linux。
  • 可能会用到的资料有如下所示,下载链接见文末:
  1. 《鸟哥的Linux私房菜 基础学习篇 第四版》1
  2. 《鸟哥的Linux私房菜 服务器架设篇 第三版》2
  3. 《韩顺平_2021图解Linux全面升级》3

22.1 Linux7启动流程介绍

22.1.1 Linux7启动流程

首先来介绍一下CentOS7的启动流程:

【参考1】CSDN博文“centos7 开机启动流程”。
【参考2】稀土掘金文章“一文快速看懂 Centos7 系统的启动过程(配思维导图)”。

图26-1 Linux7启动流程-思维导图

下面来对上图做出一些注释:

  • 第一阶段:硬件引导启动
  1. Power On:上电。
  2. BIOS:查找启动介质时会选择:光驱启动(CDROM)、USB启动、硬件启动(HDD)。
  3. MBR:会读取分区表。
  • 第二阶段:GRUB2启动引导阶段
    显示加载两个镜像,再加载MOD模块文件,把grub2程序加载执行,接着解析配置文件/boot/grub2/grub.cfg,根据配置文件加载内核镜像到内存,之后构建虚拟根文件系统,最后转到内核。

/boot/grub2/grub.cfg:是“GRUB2引导加载程序”的配置文件,用于配置操作系统的启动选项和引导过程中的各种设置,如选用哪个内核、启动模式等。之前“定制自己的linux”一章,通过修改这个文件指定哪些盘是启动盘,哪些盘是根目录。grub.cfg配置文件比较复杂,开头注释部分说明了由/etc/grub.d/目录下文件和/etc/default/grub文件组成,但在CentOS7中一般是使用命令进行配置,而无需直接修改该配置文件。一般修改好配置后都需要使用命令grub2-mkconfig -o /boot/grub2/grub.cfg,将配置文件重新生成。

  • 第三阶段:内核引导阶段
    加载驱动,切换到真正的根文件系统。

  • 第四阶段:systemed初始化阶段
    调用systemd初始化系统。

下图进一步给出了Linux7的启动流程,最关键的是第四阶段(从“调用systemd”开始)的介绍

图26-2 Linux7启动流程图

一些注意点:

  • 内核解压并自检:若内核有问题,跑不起来。
  • 由虚拟根目录切换回磁盘根目录:这个时候磁盘就找到了。
  • 调用muliti-user.target:表示“多用户模式”。
  • 启动本级别对应的服务:比如本级别定义的自启服务,可以使用指令systemctl来更改这些要自启的服务。
  • 调用/etc/rc.d/rc.local:定义开机后需要自启的自定义脚本。

最关键的第四阶段(“多用户模式”作为演示示例):

  1. 执行默认target配置文件/etc/systemd/system/default.target(这是一个软链接,与默认运行级别有关)。
  2. 并发执行sysinit.target来初始化系统和basic.target来准备操作系统。
  3. 并发启动multi-user.target下的本机与服务器服务,并检查/etc/rc.d/rc.local文件是否有用户自定义脚本需要启动。
  4. 最后执行multi-user下的getty.target及登录服务,检查default.target是否有其他的服务需要启动。

显然在上述“调用systemd”启动的过程中调用了很多系统配置文件,下面简单对这些文件的依赖关系做出示意:

/lib/systemd/system/
依赖
依赖
依赖
指向
指向
graphical.target
multiuser.target
basic.target
sysinit.target
/etc/systemd/system/default.target
图26-3 .target文件依赖关系

如上图所示:/etc/systemd/system/default.target指向了/lib/systemd/system/目录下的graphical.targetmultiuser.target。而graphical.target依赖multiuser.targetmultiuser.target依赖basic.targetbasic.target依赖sysinit.target,所以倒过来执行。

最后是chatgpt的简单总结:

  1. BIOS/UEFI 启动:计算机首先执行 BIOS 或 UEFI 中的引导程序,查找可引导的设备。一般来说,它会查找磁盘或其他存储设备以加载引导加载程序。
  2. 引导加载程序(GRUB2):GRUB2 是 CentOS 7 默认使用的引导加载程序。GRUB2 负责显示引导菜单,其中列出了可用的内核选项。
  3. 加载内核和 initramfs:一旦用户选择内核选项,GRUB2 会加载指定的内核文件(vmlinuz),同时加载相关的 initramfs(初始化 RAM Disk)。initramfs 是一个临时文件系统,包含了内核启动所需的文件和驱动程序。
  4. 内核初始化和启动 init:内核初始化时,它会检测硬件、加载驱动程序并设置系统参数。然后,内核启动第一个用户空间进程,这通常是 systemd 初始化进程。
  5. systemd 初始化:systemd 是 CentOS 7 默认使用的初始化系统,它负责启动和管理系统的各种服务。systemd 启动一系列的目标(target),每个目标包含要同时启动的一组服务。
  6. 运行级别(Runlevel)切换:在过去的 SysVinit 系统中,运行级别定义了系统在不同模式下启动的配置。在 CentOS 7 中,systemd 引入了目标(target)的概念,取代了运行级别。
  7. 启动服务和进程:在所选的目标中,systemd 启动相关的服务和进程。这可能涉及网络、文件系统、登录管理、时间同步等各种服务。
  8. 启动显示管理器(如果有):如果您的系统配置了图形用户界面(GUI),systemd 可能会启动 X Window 系统或其他显示管理器,显示登录界面。
  9. 用户登录:最终,系统会显示登录界面,用户可以通过图形界面或终端登录。

总之,CentOS 7 的启动流程涉及硬件初始化、加载内核、初始化 RAM Disk、启动用户空间、systemd 初始化和服务启动等步骤。每个步骤都是为了确保系统能够成功启动并准备好接受用户登录和任务执行。

22.1.3 systemd概述

  本小节简单介绍一下systemd初始化系统。systemd(system daemon)是Linux下的一种init软件,开发目标是提供更优秀的框架以表示系统服务间的以来关系,并依此实现系统初始化时服务的并行启动,同时达到降低Shell系统开销的效果,最终代替了之前的System V与BSD风格的init程序。与多数发行版使用的System V风格的init相比,systemd采用了以下的新技术:

  1. 采用Socket激活式与总线激活式服务,以提高相互依赖的各服务的并行运行性能。
  2. 用Cgroup代替PID来追踪进程,即使是两次fork之后生成的守护进程也不会脱离systemd的控制。

注:CentOS6使用SysVinit初始化系统,CentOS7中则替换成了systemd初始化系统。

  “unit对象”则表示不同类型的systemd对象,通过配置文件进行标识和配置;文件中主要包含了系统服务、监听socket、保存的系统快照以及其他与init相关的信息(也就是CentOS6中的服务器启动脚本)。

下面介绍四个与systemd相关的目录:
【目录1】/etc/systemd/system/default.target

这是一个软链接,指向默认运行级别,比如现在的默认运行级别为graphical.target,那么这个软链接就指向该运行级别:

[root@CentOS76 ~]# ll /etc/systemd/system/default.target
lrwxrwxrwx. 1 root root 36 129 15:47 /etc/systemd/system/default.target -> /lib/systemd/system/graphical.target

当然,存放默认运行级别文件的目录/lib/systemd/system/还有很多其他内容:

[root@CentOS76 ~]# cd /lib/systemd/system/
[root@CentOS76 ~]# ls *.target
anaconda.target            local-fs.target           runlevel2.target
basic.target               machines.target           runlevel3.target
bluetooth.target           multi-user.target         runlevel4.target
cryptsetup-pre.target      network-online.target     runlevel5.target
cryptsetup.target          network-pre.target        runlevel6.target
ctrl-alt-del.target        network.target            shutdown.target
default.target             nfs-client.target         sigpwr.target
emergency.target           nss-lookup.target         sleep.target
final.target               nss-user-lookup.target    slices.target
getty-pre.target           paths.target              smartcard.target
getty.target               poweroff.target           sockets.target
graphical.target           printer.target            sound.target
halt.target                rdma-hw.target            suspend.target
hibernate.target           reboot.target             swap.target
hybrid-sleep.target        remote-cryptsetup.target  sysinit.target
initrd-fs.target           remote-fs-pre.target      system-update.target
initrd-root-fs.target      remote-fs.target          timers.target
initrd-switch-root.target  rescue.target             time-sync.target
initrd.target              rpcbind.target            umount.target
iprutils.target            rpc_pipefs.target         virt-guest-shutdown.target
kexec.target               runlevel0.target
local-fs-pre.target        runlevel1.target

其中runlevel开头的target文件,对应着CentOS6的启动级别,不过一样是软链接,指向了同目录下的其他文件,这是CentOS7对CentOS6的向下兼容:

[root@CentOS76 ~]# ll runlevel*.target
lrwxrwxrwx. 1 root root 15 45 22:10 runlevel0.target -> poweroff.target
lrwxrwxrwx. 1 root root 13 45 22:10 runlevel1.target -> rescue.target
lrwxrwxrwx. 1 root root 17 45 22:10 runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 45 22:10 runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 45 22:10 runlevel4.target -> multi-user.target
lrwxrwxrwx. 1 root root 16 45 22:10 runlevel5.target -> graphical.target
lrwxrwxrwx. 1 root root 13 45 22:10 runlevel6.target -> reboot.target

可以看到default.target与runlevel5.target指向的是同一个文件,可以当前系统的默认运行级别是5。

【目录2】/usr/lib/systemd/system/

这个目录存储每个服务的脚本,类似CentOS6的/etc/init.d/

[root@CentOS76 ~]# ls /usr/lib/systemd/system/
abrt-ccpp.service                        halt.target                            plymouth-quit-wait.service                     svnserve.service
abrtd.service                            halt.target.wants                      plymouth-read-write.service                    swap.target
abrt-oops.service                        hibernate.target                       plymouth-reboot.service                        sys-fs-fuse-connections.mount
abrt-pstoreoops.service                  hybrid-sleep.target                    plymouth-start.service                         sysinit.target
abrt-vmcore.service                      hypervfcopyd.service                   plymouth-switch-root.service                   sysinit.target.wants
abrt-xorg.service                        hypervkvpd.service                     polkit.service                                 sys-kernel-config.mount
accounts-daemon.service                  hypervvssd.service                     postfix.service                                sys-kernel-debug.mount
alsa-restore.service                     initial-setup-graphical.service        poweroff.target                                syslog.socket
alsa-state.service                       initial-setup-reconfiguration.service  poweroff.target.wants                          syslog.target.wants
anaconda-direct.service                  initial-setup.service                  printer.target                                 sysstat.service
anaconda-nm-config.service               initial-setup-text.service             proc-fs-nfsd.mount                             systemd-ask-password-console.path
anaconda-noshell.service                 initrd-cleanup.service                 proc-sys-fs-binfmt_misc.automount              systemd-ask-password-console.service
anaconda-pre.service                     initrd-fs.target                       proc-sys-fs-binfmt_misc.mount                  systemd-ask-password-plymouth.path
anaconda.service                         initrd-parse-etc.service               psacct.service                                 systemd-ask-password-plymouth.service
anaconda-shell@.service                  initrd-root-fs.target                  qemu-guest-agent.service                       systemd-ask-password-wall.path
anaconda-sshd.service                    initrd-switch-root.service             quotaon.service                                systemd-ask-password-wall.service
anaconda.target                          initrd-switch-root.target              radvd.service                                  systemd-backlight@.service
anaconda-tmux@.service                   initrd-switch-root.target.wants        rc-local.service                               systemd-binfmt.service
arp-ethers.service                       initrd.target                          rdisc.service                                  systemd-bootchart.service
atd.service                              initrd.target.wants                    rdma-hw.target                                 systemd-firstboot.service
auditd.service                           initrd-udevadm-cleanup-db.service      rdma-load-modules@.service                     systemd-fsck-root.service
auth-rpcgss-module.service               instperf.service                       rdma-ndd.service                               systemd-fsck@.service
autofs.service                           iprdump.service                        rdma.service                                   systemd-halt.service
autovt@.service                          iprinit.service                        realmd.service                                 systemd-hibernate-resume@.service
avahi-daemon.service                     iprupdate.service                      reboot.target                                  systemd-hibernate.service
avahi-daemon.socket                      iprutils.target                        reboot.target.wants                            systemd-hostnamed.service
basic.target                             ipsec.service                          remote-cryptsetup.target                       systemd-hwdb-update.service
basic.target.wants                       irqbalance.service                     remote-fs-pre.target                           systemd-hybrid-sleep.service
blk-availability.service                 iscsid.service                         remote-fs.target                               systemd-importd.service
bluetooth.service                        iscsid.socket                          rescue.service                                 systemd-initctl.service
bluetooth.target                         iscsi-onboot.service                   rescue.target                                  systemd-initctl.socket
bolt.service                             iscsi.service                          rescue.target.wants                            systemd-journal-catalog-update.service
brandbot.path                            iscsi-shutdown.service                 rhel-autorelabel-mark.service                  systemd-journald.service
brandbot.service                         iscsiuio.service                       rhel-autorelabel.service                       systemd-journald.socket
brltty.service                           iscsiuio.socket                        rhel-configure.service                         systemd-journal-flush.service
canberra-system-bootup.service           kdump.service                          rhel-dmesg.service                             systemd-kexec.service
canberra-system-shutdown-reboot.service  kexec.target                           rhel-domainname.service                        systemd-localed.service
canberra-system-shutdown.service         kexec.target.wants                     rhel-import-state.service                      systemd-logind.service
certmonger.service                       kmod-static-nodes.service              rhel-loadmodules.service                       systemd-machined.service
cgconfig.service                         kpatch.service                         rhel-readonly.service                          systemd-machine-id-commit.service
cgdcbxd.service                          ksm.service                            rngd.service                                   systemd-modules-load.service
cgred.service                            ksmtuned.service                       rpcbind.service                                systemd-nspawn@.service
chrony-dnssrv@.service                   libstoragemgmt.service                 rpcbind.socket                                 systemd-poweroff.service
chrony-dnssrv@.timer                     libvirtd.service                       rpcbind.target                                 systemd-quotacheck.service
chronyd.service                          lldpad.service                         rpc-gssd.service                               systemd-random-seed.service
chrony-wait.service                      lldpad.socket                          rpcgssd.service                                systemd-readahead-collect.service
clean-mount-point@.service               local-fs-pre.target                    rpcidmapd.service                              systemd-readahead-done.service
colord.service                           local-fs.target                        rpc_pipefs.target                              systemd-readahead-done.timer
configure-printer@.service               local-fs.target.wants                  rpc-rquotad.service                            systemd-readahead-drop.service
console-getty.service                    lvm2-lvmetad.service                   rpc-statd-notify.service                       systemd-readahead-replay.service
console-shell.service                    lvm2-lvmetad.socket                    rpc-statd.service                              systemd-reboot.service
container-getty@.service                 lvm2-lvmpolld.service                  rsyncd.service                                 systemd-remount-fs.service
cpupower.service                         lvm2-lvmpolld.socket                   rsyncd@.service                                systemd-rfkill@.service
crond.service                            lvm2-monitor.service                   rsyncd.socket                                  systemd-shutdownd.service
cryptsetup-pre.target                    lvm2-pvscan@.service                   rsyslog.service                                systemd-shutdownd.socket
cryptsetup.target                        machine.slice                          rtkit-daemon.service                           systemd-suspend.service
ctrl-alt-del.target                      machines.target                        runlevel0.target                               systemd-sysctl.service
cups-browsed.service                     mdadm-grow-continue@.service           runlevel1.target                               systemd-timedated.service
cups.path                                mdadm-last-resort@.service             runlevel1.target.wants                         systemd-tmpfiles-clean.service
cups.service                             mdadm-last-resort@.timer               runlevel2.target                               systemd-tmpfiles-clean.timer
cups.socket                              mdcheck_continue.service               runlevel2.target.wants                         systemd-tmpfiles-setup-dev.service
dbus-org.freedesktop.hostname1.service   mdcheck_continue.timer                 runlevel3.target                               systemd-tmpfiles-setup.service
dbus-org.freedesktop.import1.service     mdcheck_start.service                  runlevel3.target.wants                         systemd-udevd-control.socket
dbus-org.freedesktop.locale1.service     mdcheck_start.timer                    runlevel4.target                               systemd-udevd-kernel.socket
dbus-org.freedesktop.login1.service      mdmonitor-oneshot.service              runlevel4.target.wants                         systemd-udevd.service
dbus-org.freedesktop.machine1.service    mdmonitor-oneshot.timer                runlevel5.target                               systemd-udev-settle.service
dbus-org.freedesktop.timedate1.service   mdmonitor.service                      runlevel5.target.wants                         systemd-udev-trigger.service
dbus.service                             mdmon@.service                         runlevel6.target                               systemd-update-done.service
dbus.socket                              messagebus.service                     run-vmblock\x2dfuse.mount                      systemd-update-utmp-runlevel.service
dbus.target.wants                        microcode.service                      saned@.service                                 systemd-update-utmp.service
debug-shell.service                      ModemManager.service                   saned.socket                                   systemd-user-sessions.service
default.target                           multipathd.service                     saslauthd.service                              systemd-vconsole-setup.service
default.target.wants                     multi-user.target                      selinux-policy-migrate-local-changes@.service  system.slice
dev-hugepages.mount                      multi-user.target.wants                serial-getty@.service                          system-update.target
dev-mqueue.mount                         mysqld.service                         shutdown.target                                system-update.target.wants
dm-event.service                         mysqld@.service                        shutdown.target.wants                          targetclid.service
dm-event.socket                          ndctl-monitor.service                  sigpwr.target                                  targetclid.socket
dmraid-activation.service                netcf-transaction.service              sleep.target                                   target.service
dnsmasq.service                          NetworkManager-dispatcher.service      -.slice                                        tcsd.service
dracut-cmdline.service                   NetworkManager.service                 slices.target                                  teamd@.service
dracut-initqueue.service                 NetworkManager-wait-online.service     smartcard.target                               timers.target
dracut-mount.service                     network-online.target                  smartd.service                                 timers.target.wants
dracut-pre-mount.service                 network-pre.target                     sockets.target                                 time-sync.target
dracut-pre-pivot.service                 network.target                         sockets.target.wants                           tmp.mount
dracut-pre-trigger.service               nfs-blkmap.service                     sound.target                                   tuned.service
dracut-pre-udev.service                  nfs-client.target                      sound.target.wants                             udisks2.service
dracut-shutdown.service                  nfs-config.service                     speech-dispatcherd.service                     umount.target
ebtables.service                         nfs-idmapd.service                     spice-vdagentd.service                         unbound-anchor.service
emergency.service                        nfs-idmap.service                      spice-vdagentd.socket                          unbound-anchor.timer
emergency.target                         nfs-lock.service                       sshd-keygen.service                            upower.service
fcoe.service                             nfslock.service                        sshd.service                                   usb_modeswitch@.service
final.target                             nfs-mountd.service                     sshd@.service                                  usbmuxd.service
firewalld.service                        nfs-rquotad.service                    sshd.socket                                    user.slice
firstboot-graphical.service              nfs-secure.service                     sssd-autofs.service                            var-lib-nfs-rpc_pipefs.mount
flatpak-system-helper.service            nfs-server.service                     sssd-autofs.socket                             vdo.service
fprintd.service                          nfs.service                            sssd-nss.service                               vdo-start-by-dev@.service
fstrim.service                           nfs-utils.service                      sssd-nss.socket                                vgauthd.service
fstrim.timer                             nss-lookup.target                      sssd-pac.service                               virt-guest-shutdown.target
fwupdate-cleanup.service                 nss-user-lookup.target                 sssd-pac.socket                                virtlockd-admin.socket
fwupd-offline-update.service             ntpdate.service                        sssd-pam-priv.socket                           virtlockd.service
fwupd.service                            ntpd.service                           sssd-pam.service                               virtlockd.socket
gdm.service                              numad.service                          sssd-pam.socket                                virtlogd-admin.socket
geoclue.service                          oddjobd.service                        sssd-secrets.service                           virtlogd.service
getty-pre.target                         packagekit-offline-update.service      sssd-secrets.socket                            virtlogd.socket
getty@.service                           packagekit.service                     sssd.service                                   vmtoolsd.service
getty.target                             paths.target                           sssd-ssh.service                               wacom-inputattach@.service
graphical.target                         plymouth-halt.service                  sssd-ssh.socket                                wpa_supplicant.service
graphical.target.wants                   plymouth-kexec.service                 sssd-sudo.service                              zram.service
gssproxy.service                         plymouth-poweroff.service              sssd-sudo.socket
halt-local.service                       plymouth-quit.service                  suspend.target

【目录3】/run/systemd/system/

系统执行过程中产生的脚本:

[root@CentOS76 ~]# ls /run/systemd/system/
session-1.scope    session-2.scope    session-767.scope    session-797.scope    user-0.slice    user-1000.slice
session-1.scope.d  session-2.scope.d  session-767.scope.d  session-797.scope.d  user-0.slice.d  user-1000.slice.d

【目录4】/etc/systemd/system/

类似于CentOS6的/etc/rc.d/rc#.d/SXX类文件的功能,管理员建立的执行脚本,大部分是软链接

[root@CentOS76 ~]# ls /etc/systemd/system/
basic.target.wants                          dbus-org.freedesktop.nm-dispatcher.service               graphical.target.wants       remote-fs.target.wants
bluetooth.target.wants                      default.target                                           local-fs.target.wants        sockets.target.wants
dbus-org.bluez.service                      default.target.wants                                     multi-user.target.wants      sysinit.target.wants
dbus-org.fedoraproject.FirewallD1.service   dev-virtio\x2dports-org.qemu.guest_agent.0.device.wants  network-online.target.wants  system-update.target.wants
dbus-org.freedesktop.Avahi.service          display-manager.service                                  oneavd.service               timers.target.wants
dbus-org.freedesktop.ModemManager1.service  getty.target.wants                                       printer.target.wants         vmtoolsd.service.requires

22.2 *制作min-linux思路分析

  本节标*号表明是本章重点,最关键的min-linux制作思路将在下面说明。通过裁剪现有Linux系统(CentOS7.6),创建属于自己的min Linux小系统,可以加深我们对linux运行机制的理解,比如Linux是如何开机、如何引导、如何加载相关文件等。首先按照上一节的介绍,继续简化一下启动流程的说明:

1、首先Linux要通过自检,检查硬件设备有没有故障。
2、如果有多块启动盘的话,需要在BIOS中选择启动磁盘。
3、启动MBR中的bootloader引导程序。
4、加载内核文件。
5、执行所有进程的父进程、老祖宗systemd。
6、欢迎界面。

于是制作一个min-linux的原则就是只保留与启动相关的部分,剔除其余所有部分,思路如下(如下图):

  1. 创建新磁盘。
    在现有的Linux系统(centos7.6)上添加一块磁盘/dev/sdb,并添加两个分区:启动分区/boot、根分区/,然后将其格式化,新磁盘创建完成。

注:需要明确的是,现在加的这个磁盘在现有的Linux系统中是/dev/sdb,但是,当我们把东西全部设置好时,要把这个磁盘拔除并放在新系统上,就是新系统的/dev/sda

  1. 制作启动盘。
    本步骤的目的就是将/dev/sdb磁盘打造成独立的Linux系统,里面的所有系统启动的必备文件都需要从当前系统的/dev/sda拷贝。

a) 挂载磁盘。首先在系统中创建新系统的boot分区目录/mnt/boot、根分区目录/mnt/sysroot。然后将/dev/sdb磁盘上的sdb1、sdb2分别挂载到这两个目录上。
b) 制作/boot分区。安装grub引导程序。然后将/boot分区所有内容拷贝至/mnt/boot。然后修改 grub2/grub.cfg文件,指定哪些盘是启动盘、哪些盘是根目录。
c) 制作根分区。创建根目录/下的重要目录、拷贝必要的库目录/lib4/、shell命令解释器/bin/bash

  1. 创建新的虚拟机min-linux。
    在VMware创建一个新的虚拟机,然后移出默认分配的磁盘,将上述制作好的启动盘挂载到该新系统上,即可启动。
  2. 添加指令。
    虽然在“制作启动盘”时已经添加了库文件和Shell解释器,但几乎所有指令都存放在/bin/sbin目录下,并且这些指令加在一起异常庞大,所以只有最基本的指令(如cd)添加到了启动盘中。若想使用其他指令(如lsreboot等),就需要额外添加指令。

以上步骤完成,我们的自制Linux就完成,创建一个新的Linux虚拟机,将其磁盘指向我们创建的磁盘,启动即可。

挂载原本的磁盘
挂载新的磁盘
作为sda磁盘
挂载到新的虚拟机上
sdb磁盘
/boot分区
根分区
Linux虚拟机-CentOS76
/mnt/boot
/mnt/sysroot
sda磁盘
/boot
swap
/[/bin,/sbin,...]
Linux虚拟机-minLinux
注:紫色是原来的,黄色是新创建的
图26-4 制作min-linux思路分析

22.3 操作步骤

步骤1:创建新磁盘

本步骤的目的是在原本的虚拟机(CentOS7.6)下创建一块新的磁盘,具体的步骤如下:

  1. VMware添加新磁盘。
  2. 磁盘分区。
  3. 磁盘格式化。

1. VMware添加新磁盘

首先将旧虚拟机关机,然后按照下面的步骤在VMware添加新磁盘,最后开启旧虚拟机。我们先假设这块磁盘的大小为20G。

图26-5 VMware创建新磁盘

开机后,使用root登录,在桌面右键“打开终端”,即可使用lsblk看到新添加的sdb磁盘:

[root@CentOS76 ~]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0   20G  0 disk 
├─sda1   8:1    0    1G  0 part /boot
├─sda2   8:2    0    2G  0 part [SWAP]
└─sda3   8:3    0   17G  0 part /
sdb      8:16   0   20G  0 disk 
sr0     11:0    1  4.4G  0 rom  /run/media/root/CentOS 7 x86_64

2. 磁盘分区

然后使用指令fdisk对sdb磁盘(20G)进行分区,其中500MB分配给之后的引导分区/boot,剩下的空间都分配给之后的根分区。

[root@CentOS76 ~]# fdisk /dev/sdb
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

Device does not contain a recognized partition table
使用磁盘标识符 0x1770f9c6 创建新的 DOS 磁盘标签。

命令(输入 m 获取帮助):n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): 
Using default response p
分区号 (1-4,默认 1):
起始 扇区 (2048-41943039,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-41943039,默认为 41943039):+500M
分区 1 已设置为 Linux 类型,大小设为 500 MiB

命令(输入 m 获取帮助):n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): 
Using default response p
分区号 (2-4,默认 2):
起始 扇区 (1026048-41943039,默认为 1026048):
将使用默认值 1026048
Last 扇区, +扇区 or +size{K,M,G} (1026048-41943039,默认为 41943039):
将使用默认值 41943039
分区 2 已设置为 Linux 类型,大小设为 19.5 GiB

命令(输入 m 获取帮助):w
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。

分区完成后可再次查看磁盘情况,可以看到已经有了分区sdb1sdb2,但都没有挂载点:

[root@CentOS76 ~]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0   20G  0 disk 
├─sda1   8:1    0    1G  0 part /boot
├─sda2   8:2    0    2G  0 part [SWAP]
└─sda3   8:3    0   17G  0 part /
sdb      8:16   0   20G  0 disk 
├─sdb1   8:17   0  500M  0 part 
└─sdb2   8:18   0 19.5G  0 part 
sr0     11:0    1  4.4G  0 rom  /run/media/root/CentOS 7 x86_64

3. 磁盘格式化

本步骤将sdb磁盘中所有的分区(sdb1sdb2)都进行格式化,是为了生成各个分区的UUID,以进行后续磁盘挂载:

################## 指令速览 #####################
mkfs.ext4 /dev/sdb1
mkfs.ext4 /dev/sdb2

################## 实际演示 #####################
[root@CentOS76 ~]# mkfs.ext4 /dev/sdb1
mke2fs 1.42.9 (28-Dec-2013)
文件系统标签=
OS type: Linux
块大小=1024 (log=0)
分块大小=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
128016 inodes, 512000 blocks
25600 blocks (5.00%) reserved for the super user
第一个数据块=1
Maximum filesystem blocks=34078720
63 block groups
8192 blocks per group, 8192 fragments per group
2032 inodes per group
Superblock backups stored on blocks: 
	8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409

Allocating group tables: 完成                            
正在写入inode表: 完成                            
Creating journal (8192 blocks): 完成
Writing superblocks and filesystem accounting information: 完成 

[root@CentOS76 ~]# mkfs.ext4 /dev/sdb2
mke2fs 1.42.9 (28-Dec-2013)
文件系统标签=
OS type: Linux
块大小=4096 (log=2)
分块大小=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1281120 inodes, 5114624 blocks
255731 blocks (5.00%) reserved for the super user
第一个数据块=0
Maximum filesystem blocks=2153775104
157 block groups
32768 blocks per group, 32768 fragments per group
8160 inodes per group
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000

Allocating group tables: 完成                            
正在写入inode表: 完成                            
Creating journal (32768 blocks): 完成
Writing superblocks and filesystem accounting information: 完成   

到此,新磁盘就算是制作完成,下面就可以来制作启动盘了。

步骤2:制作启动盘

本步骤的目的在于利用旧虚拟机的资源制作min-linux的启动盘,具体的步骤如下:

  1. 挂载磁盘。
  2. 安装grub并拷贝/boot。
  3. 修改/mnt/boot/grub2/grub.cfg文件。
  4. 创建根文件系统。
  5. 拷贝库文件和Shell解释器。

1. 挂载磁盘

首先在旧虚拟机的系统下创建新虚拟机要用的引导分区目录/mnt/boot、根分区目录/mnt/sysroot,然后将sdb1sdb2分别挂载到这两个分区上:

注:在前面“目录结构”一章中就提到,/mnt目录就是用于让用户临时挂载别的文件系统。
注:由于了Linux新创建的目录默认都会保存在根目录的挂载磁盘(sda)上,所以挂载sdb之前的内容都会保存在sda中。挂载sdb后,新添加的内容则只会保存在sdb上。后续卸载sdb之后,旧虚拟机便只能看到两个空目录/mnt/boot/mnt/sysroot,因为这两个目录是挂载sdb之前创建的,但里面的内容是挂载sdb之后添加的所以为空。

################## 指令速览 #####################
mkdir -p /mnt/boot /mnt/sysroot     # 批量创建目录
mount /dev/sdb1 /mnt/boot           # 将sdb1挂载到引导分区
mount /dev/sdb2 /mnt/sysroot/       # 将sdb2挂载到根分区

################## 实际演示 #####################
[root@CentOS76 ~]# mkdir -p /mnt/boot /mnt/sysroot 
[root@CentOS76 ~]# mount /dev/sdb1 /mnt/boot 
[root@CentOS76 ~]# mount /dev/sdb2 /mnt/sysroot/  

2. 安装grub并拷贝/boot

使用下面的指令来安装grub、拷贝/boot分区所有内容到/mnt/boot

注:GRUB(GRand Unified Bootloader, 大一统引导程序)是一个用于加载和管理系统启动的完整程序。它是 Linux 发行版中最常见的引导程序(bootloader)。
注:下面的“安装grub”指令会自动创建目录/mnt/boot/grub2

################## 指令速览 #####################
grub2-install --root-directory=/mnt /dev/sdb    # 安装grub
hexdump -C -n 512 /dev/sdb                      # 查看二进制以确认grub是否安装成功
cp -rf /boot/* /mnt/boot/                       # 拷贝/boot分区所有内容到/mnt/boot

################## 实际演示 #####################
[root@CentOS76 ~]# grub2-install --root-directory=/mnt /dev/sdb
Installing for i386-pc platform.
Installation finished. No error reported.
[root@CentOS76 ~]# hexdump -C -n 512 /dev/sdb
00000000  eb 63 90 00 00 00 00 00  00 00 00 00 00 00 00 00  |.c..............|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000050  00 00 00 00 00 00 00 00  00 00 00 80 01 00 00 00  |................|
00000060  00 00 00 00 ff fa 90 90  f6 c2 80 74 05 f6 c2 70  |...........t...p|
00000070  74 02 b2 80 ea 79 7c 00  00 31 c0 8e d8 8e d0 bc  |t....y|..1......|
00000080  00 20 fb a0 64 7c 3c ff  74 02 88 c2 52 be 05 7c  |. ..d|<.t...R..||
00000090  b4 41 bb aa 55 cd 13 5a  52 72 3d 81 fb 55 aa 75  |.A..U..ZRr=..U.u|
000000a0  37 83 e1 01 74 32 31 c0  89 44 04 40 88 44 ff 89  |7...t21..D.@.D..|
000000b0  44 02 c7 04 10 00 66 8b  1e 5c 7c 66 89 5c 08 66  |D.....f..\|f.\.f|
000000c0  8b 1e 60 7c 66 89 5c 0c  c7 44 06 00 70 b4 42 cd  |..`|f.\..D..p.B.|
000000d0  13 72 05 bb 00 70 eb 76  b4 08 cd 13 73 0d 5a 84  |.r...p.v....s.Z.|
000000e0  d2 0f 83 de 00 be 85 7d  e9 82 00 66 0f b6 c6 88  |.......}...f....|
000000f0  64 ff 40 66 89 44 04 0f  b6 d1 c1 e2 02 88 e8 88  |d.@f.D..........|
00000100  f4 40 89 44 08 0f b6 c2  c0 e8 02 66 89 04 66 a1  |.@.D.......f..f.|
00000110  60 7c 66 09 c0 75 4e 66  a1 5c 7c 66 31 d2 66 f7  |`|f..uNf.\|f1.f.|
00000120  34 88 d1 31 d2 66 f7 74  04 3b 44 08 7d 37 fe c1  |4..1.f.t.;D.}7..|
00000130  88 c5 30 c0 c1 e8 02 08  c1 88 d0 5a 88 c6 bb 00  |..0........Z....|
00000140  70 8e c3 31 db b8 01 02  cd 13 72 1e 8c c3 60 1e  |p..1......r...`.|
00000150  b9 00 01 8e db 31 f6 bf  00 80 8e c6 fc f3 a5 1f  |.....1..........|
00000160  61 ff 26 5a 7c be 80 7d  eb 03 be 8f 7d e8 34 00  |a.&Z|..}....}.4.|
00000170  be 94 7d e8 2e 00 cd 18  eb fe 47 52 55 42 20 00  |..}.......GRUB .|
00000180  47 65 6f 6d 00 48 61 72  64 20 44 69 73 6b 00 52  |Geom.Hard Disk.R|
00000190  65 61 64 00 20 45 72 72  6f 72 0d 0a 00 bb 01 00  |ead. Error......|
000001a0  b4 0e cd 10 ac 3c 00 75  f4 c3 00 00 00 00 00 00  |.....<.u........|
000001b0  00 00 00 00 00 00 00 00  c6 f9 70 17 00 00 00 20  |..........p.... |
000001c0  21 00 83 dd 1e 3f 00 08  00 00 00 a0 0f 00 00 dd  |!....?..........|
000001d0  1f 3f 83 d4 a2 32 00 a8  0f 00 00 58 70 02 00 00  |.?...2.....Xp...|
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200
# 显示如上界面便证明grub安装成功
[root@CentOS76 ~]# cp -rf /boot/* /mnt/boot/

拷贝完成后,引导分区/mnt/boot算是已经基本完成,但是需要再修改一个关键文件:/mnt/boot/grub2/grub.cfg

3. 修改/mnt/boot/grub2/grub.cfg文件

  在本章第一节介绍“Linux7启动流程”时,便提到/boot/grub2/grub.cfg是“GRUB2引导加载程序”的配置文件,用于配置操作系统的启动选项和引导过程中的各种设置,如选用哪个内核、启动模式等。内核和启动模式等一系列内容都可以和旧虚拟机保持相同,我们并不关心,但是“启动盘”和“根目录盘”应该调整为新创建的sdb1sdb2,而不是旧虚拟机的sda下的分区

下面是/mnt/boot/grub2/grub.cfg文件的内容:

#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub2-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
set pager=1

if [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}

function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

terminal_output console
if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=5
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/00_tuned ###
set tuned_params=""
set tuned_initrd=""
### END /etc/grub.d/00_tuned ###

### BEGIN /etc/grub.d/01_users ###
if [ -f ${prefix}/user.cfg ]; then
  source ${prefix}/user.cfg
  if [ -n "${GRUB2_PASSWORD}" ]; then
    set superusers="root"
    export superusers
    password_pbkdf2 root ${GRUB2_PASSWORD}
  fi
fi
### END /etc/grub.d/01_users ###

### BEGIN /etc/grub.d/10_linux ###
menuentry 'CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  2e1b1edd-64e9-43f0-9362-138e2bd6adc5
        else
          search --no-floppy --fs-uuid --set=root 2e1b1edd-64e9-43f0-9362-138e2bd6adc5
        fi
        linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=UUID=43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe ro rhgb quiet LANG=zh_CN.UTF-8
        initrd16 /initramfs-3.10.0-1160.el7.x86_64.img
}
menuentry 'CentOS Linux (0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        else
          search --no-floppy --fs-uuid --set=root 2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        fi
        linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=UUID=43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe ro rhgb quiet LANG=zh_CN.UTF-8    # 这里是sda3的UUID
        initrd16 /initramfs-3.10.0-1160.el7.x86_64.img
}
menuentry 'CentOS Linux (0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        else
          search --no-floppy --fs-uuid --set=root 2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        fi
        linux16 /vmlinuz-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d root=UUID=43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe ro rhgb quiet    # 这里是sda3的UUID
        initrd16 /initramfs-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d.img
}

### END /etc/grub.d/10_linux ###

### BEGIN /etc/grub.d/20_linux_xen ###
### END /etc/grub.d/20_linux_xen ###

### BEGIN /etc/grub.d/20_ppc_terminfo ###
### END /etc/grub.d/20_ppc_terminfo ###

### BEGIN /etc/grub.d/30_os-prober ###
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###

### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
  source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
  source $prefix/custom.cfg;
fi
### END /etc/grub.d/41_custom ###

我们只关心其中的这一段使用UUID规定了引导盘和启动盘的内容,进一步的,也就是其中6行有中文注释的内容(两个sda1、一个sda3、两个sda1、一个sda3)。显然结合当前虚拟机的磁盘信息,这6行指令规定了sda1为/boot分区、sda3为/根分区:

注:这6行中文注释,是我自己加的,原始文件中没有。

# 当前虚拟机的磁盘信息
[root@CentOS76 grub2]# lsblk -f
NAME   FSTYPE  LABEL           UUID                                 MOUNTPOINT
sda                                                                 
├─sda1 ext4                    2e1b1edd-64e9-43f0-9362-138e2bd6adc5 /boot
├─sda2 swap                    7e2d03c3-f47a-4721-b29d-1a7b9170fe61 [SWAP]
└─sda3 ext4                    43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe /
sdb                                                                 
├─sdb1 ext4                    78e5821e-673e-4cb3-9f56-596ff44c449d /mnt/boot
└─sdb2 ext4                    93f8a2dc-b54f-42c0-bfe5-9da618fc51b9 /mnt/sysroot
sr0    iso9660 CentOS 7 x86_64 2020-11-04-11-36-43-00               /run/media/root/CentOS 7 x86_64
### BEGIN /etc/grub.d/10_linux ###
menuentry 'CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  2e1b1edd-64e9-43f0-9362-138e2bd6adc5
        else
          search --no-floppy --fs-uuid --set=root 2e1b1edd-64e9-43f0-9362-138e2bd6adc5
        fi
        linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=UUID=43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe ro rhgb quiet LANG=zh_CN.UTF-8
        initrd16 /initramfs-3.10.0-1160.el7.x86_64.img
}
menuentry 'CentOS Linux (0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        else
          search --no-floppy --fs-uuid --set=root 2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        fi
        linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=UUID=43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe ro rhgb quiet LANG=zh_CN.UTF-8    # 这里是sda3的UUID
        initrd16 /initramfs-3.10.0-1160.el7.x86_64.img
}
menuentry 'CentOS Linux (0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        else
          search --no-floppy --fs-uuid --set=root 2e1b1edd-64e9-43f0-9362-138e2bd6adc5    # 这里是sda1的UUID
        fi
        linux16 /vmlinuz-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d root=UUID=43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe ro rhgb quiet    # 这里是sda3的UUID
        initrd16 /initramfs-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d.img
}

### END /etc/grub.d/10_linux ###

下面仅需修改这6行内容,来指定sdb1为引导分区/boot、sdb2为根分区,具体修改方法如下:

  1. sda1的UUID换成sdb1的UUID,将sda3的UUID换成sdb2的UUID。
  2. sdb2的UUID所在的两行最后添加一句话:selinux=0 init=/bin/bash,表示selinux给关掉,同时设定一下init,告诉内核不要再去找这个程序了,不然开机的时候会出现错误的。

注:其他地方可能还有一些sda磁盘分区的信息,不要紧,新虚拟机min-linux开机后会自动覆写这些UUID。

### BEGIN /etc/grub.d/10_linux ###
menuentry 'CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  78e5821e-673e-4cb3-9f56-596ff44c449d    # 这里是sdb1的UUID
        else
          search --no-floppy --fs-uuid --set=root 78e5821e-673e-4cb3-9f56-596ff44c449d    # 这里是sdb1的UUID
        fi
        linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=UUID=93f8a2dc-b54f-42c0-bfe5-9da618fc51b9 ro rhgb quiet LANG=zh_CN.UTF-8 selinux=0 init=/bin/bash    # 这里是sdb2的UUID,并添加了一句话
        initrd16 /initramfs-3.10.0-1160.el7.x86_64.img
}
menuentry 'CentOS Linux (0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d-advanced-43bc1b00-e520-4cfb-8c4b-8f0afbde5dbe' {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  78e5821e-673e-4cb3-9f56-596ff44c449d    # 这里是sdb1的UUID
        else
          search --no-floppy --fs-uuid --set=root 78e5821e-673e-4cb3-9f56-596ff44c449d    # 这里是sdb1的UUID
        fi
        linux16 /vmlinuz-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d root=UUID=93f8a2dc-b54f-42c0-bfe5-9da618fc51b9 ro rhgb quiet selinux=0 init=/bin/bash    # 这里是sdb2的UUID,并添加了一句话
        initrd16 /initramfs-0-rescue-0d4bcac3ad0e4afe96e50f962baa9f7d.img
}

### END /etc/grub.d/10_linux ###

改完后如上所示。此时整个引导分区/mnt/boot就创建完成。虽然能启动,但是根目录下还有/bin、系统公用的库文件等一大堆的指令文件,若没有这些文件,连Shell解释器都进入不了,所以现在就来拷贝这些文件来完善根分区。

4. 创建根文件系统
现在就是在sdb2(新的根目录)下将重要的目录都建起来:

################## 指令速览 #####################
mkdir -pv /mnt/sysroot/{etc/rc.d,usr,var,proc,sys,dev,lib,lib64,bin,sbin,boot,srv,mnt,media,home,root}

################## 实际演示 #####################
[root@CentOS76 grub2]# mkdir -pv /mnt/sysroot/{etc/rc.d,usr,var,proc,sys,dev,lib,lib64,bin,sbin,boot,srv,mnt,media,home,root}
mkdir: 已创建目录 "/mnt/sysroot/etc"
mkdir: 已创建目录 "/mnt/sysroot/etc/rc.d"
mkdir: 已创建目录 "/mnt/sysroot/usr"
mkdir: 已创建目录 "/mnt/sysroot/var"
mkdir: 已创建目录 "/mnt/sysroot/proc"
mkdir: 已创建目录 "/mnt/sysroot/sys"
mkdir: 已创建目录 "/mnt/sysroot/dev"
mkdir: 已创建目录 "/mnt/sysroot/lib"
mkdir: 已创建目录 "/mnt/sysroot/lib64"
mkdir: 已创建目录 "/mnt/sysroot/bin"
mkdir: 已创建目录 "/mnt/sysroot/sbin"
mkdir: 已创建目录 "/mnt/sysroot/boot"
mkdir: 已创建目录 "/mnt/sysroot/srv"
mkdir: 已创建目录 "/mnt/sysroot/mnt"
mkdir: 已创建目录 "/mnt/sysroot/media"
mkdir: 已创建目录 "/mnt/sysroot/home"
mkdir: 已创建目录 "/mnt/sysroot/root"

5. 拷贝库文件和Shell解释器
首先拷贝库文件、bash到新的根分区。完成后,根分区也制作完成,此时就可以将旧虚拟机关机,使得新系统可以使用该磁盘:

################## 指令速览 #####################
cp /lib64/*.* /mnt/sysroot/lib64/   # 拷贝公用的库,若不拷贝连最基本的指令都无法使用
cp /bin/bash /mnt/sysroot/bin/      # 将shell(命令解释器)拷贝过来
shutdown -h now                     # 关闭旧虚拟机

################## 实际演示 #####################
[root@CentOS76 grub2]# cp /lib64/*.* /mnt/sysroot/lib64/
cp: 略过目录"/lib64/db4.7.25"
cp: 略过目录"/lib64/dleyna-1.0"
cp: 略过目录"/lib64/farstream-0.1"
cp: 略过目录"/lib64/farstream-0.2"
cp: 略过目录"/lib64/gdk-pixbuf-2.0"
cp: 略过目录"/lib64/girepository-1.0"
cp: 略过目录"/lib64/gnome-settings-daemon-3.0"
cp: 略过目录"/lib64/goa-1.0"
cp: 略过目录"/lib64/grilo-0.3"
cp: 略过目录"/lib64/gstreamer-0.10"
cp: 略过目录"/lib64/gstreamer-1.0"
cp: 略过目录"/lib64/gtk-2.0"
cp: 略过目录"/lib64/gtk-3.0"
cp: 略过目录"/lib64/libcanberra-0.30"
cp: 略过目录"/lib64/libpeas-1.0"
cp: 略过目录"/lib64/mission-control-plugins.0"
cp: 略过目录"/lib64/pulse-10.0"
cp: 略过目录"/lib64/python2.7"
cp: 略过目录"/lib64/tracker-1.0"
cp: 略过目录"/lib64/vte-2.91"
cp: 略过目录"/lib64/webkit2gtk-4.0"
[root@CentOS76 grub2]# cp /bin/bash /mnt/sysroot/bin/
[root@CentOS76 grub2]# shutdown -h now

步骤3:创建min-linux虚拟机

本步骤的为创建min-linux的最后一步,主要就是创建新的VMware虚拟机,然后移出默认分配的硬盘并将刚才在旧虚拟机上配置好的启动盘添加到当前虚拟机min-linux上,即可开机。具体的步骤如下:

  1. 创建min-linux虚拟机。
  2. 移除默认磁盘并添加启动盘。
  3. 开机测试。

1. 创建min-linux虚拟机

在VMware菜单栏选择“文件”–>“新建虚拟机”,然后按照下图所示进行操作:

图26-6 创建min-linux虚拟机

2. 移除默认磁盘并添加启动盘
在创建min-linux时,VMware的引导程序显然创建了默认硬盘,下面我们移出这个默认的硬盘,并将上一小节制作好的启动盘添加到当前系统中。如下图所示操作:

图26-7 更换min-linux硬盘

3. 开机测试

上述硬盘更换完成后即可开机测试指令,如下所示则证明系统可以正常运行:

图26-8 min-linux开机测试

测试完成后,发现虽然系统可以正常运行,但是居然来连ls指令都无法使用,所以下面如果有需求的话,还可以在向min-linux添加一些指令。

步骤4(选做):添加额外的指令

由于Linux系统的指令一般都存放在/bin/sbin目录下,所以向min-linux添加指令的思路很简单:

  1. 关闭min-linux,开启旧虚拟机。
  2. sdb2重新挂载到根分区新虚拟机的根分区/mnt/sysroot上,然后拷贝旧虚拟机/bin/sbin目录下的指令到对应的/mnt/sysroot/bin/mnt/sysroot/sbin目录下。
  3. 关闭旧虚拟机,开启min-linux,即可运行新指令。

注:不要一股脑将所有指令都拷贝过去,因为某些指令文件很大,制作min-linux的初衷只是能运行的最小linux系统,这样的系统通常是运行在低功耗的物联网小模块中,并不要求该系统有很好的人机交互功能。

下面是在旧虚拟机上的操作(仅拷贝了lsrebootsystenctl):

[root@CentOS76 ~]# mount /dev/sdb2 /mnt/sysroot/
[root@CentOS76 ~]# cp /bin/ls /mnt/sysroot/bin/
[root@CentOS76 ~]# cp /bin/systemctl  /mnt/sysroot/bin/
[root@CentOS76 ~]# cp /sbin/reboot  /mnt/sysroot/sbin/
[root@CentOS76 grub2]# shutdown -h now

下面是最后开启min-linux后,新添加指令的运行情况示意图和代码块注释:

图22-9 min-linux运行新指令
bash-4.2# cd /
bash-4.2# ls                # 主要还是不能直接使用ls
bash: ls: command not f ound
bash-4.Z# /bin/ls 
bin boot dev etc home lib lib64 lost+found media mnt proc root sbin srv sys usr var
bash-4.2# /bin/ls -l /bin   # 需要写清楚指令所在目录
total 1768
-rwxr-xr-x. 1 0 0 964536 Aug 23 01:32 bash
-rwxr-xr-x. 1 0 0 117608 Aug 23 02:02 ls
-rwxr-xr-x. 1 0 0 721744 Aug 23 02:03 systemctl 
bash-4.2# /bin/ls -l /sbin
total 708
-rwxr-xr-x. 1 0 0 721744 Aug 23 02:03 reboot
bash-4.2# /sbin/reboot      # 直接调用reboot不好使
Failed to talk to init daemon.
bash-4.2# /sbin/reboot -f   # 强制重启好使

最后可以看到,min-linux的大小是真的小!!

图22-10 虚拟机文件夹大小对比

  1. 《鸟哥的Linux私房菜 基础学习篇 第四版》 ↩︎

  2. 《鸟哥的Linux私房菜 服务器架设篇 第三版》 ↩︎

  3. 《韩顺平_2021图解Linux全面升级》 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/951337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个简单的vim例子

一.欢迎来到我的酒馆 在本章节介绍vim工具。 目录 一.欢迎来到我的酒馆二.什么是vim 二.什么是vim 2.1什么是vim vim是一种Linux命令行类型 的文本编辑器。vim指的是"vi improved"&#xff0c;意思是vi工具的升级版。vim是基于vi实现的&#xff0c;它提供了…

设计模式--模板方法模式(Template Method Pattern)

一、什么是模板方法模式&#xff08;Template Method Pattern&#xff09; 模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;将一些步骤的实现延迟到子类中。模板方法模式允许在不改变算法的…

视频汇聚/视频云存储/视频监控管理平台EasyCVR新增首次登录强制修改密码

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚平台既具…

Quartus II安装下载驱动

Quartus II安装下载驱动 安装步骤&#xff1a; &#xff08;1&#xff09;安装完quartus后会自带USB-Blaster的驱动程序&#xff0c;因此不用再去网上下载。 &#xff08;2&#xff09;右键点脑左下角win&#xff0c;找到设备管理器并进入。 &#xff08;3&#xff09;找到…

QT 常用类与组件

0 思维导图 1 信息调试类&#xff08;QDebug&#xff09; #include "widget.h" #include<iostream> //printf #include<QDebug> //qDebuf using namespace std; //coutWidget::Widget(QWidget *parent): QWidget(parent) {//输出函数//使用…

【python爬虫】—图片爬取

图片爬取 需求分析Python实现 需求分析 从https://pic.netbian.com/4kfengjing/网站爬取图片&#xff0c;并保存 Python实现 获取待爬取网页 def get_htmls(pageslist(range(2, 5))):"""获取待爬取网页"""pages_list []for page in pages:u…

[Pandas] 求百分比并添加百分(%)号

导入数据 import pandas as pddf pd.DataFrame(data{orders: [2130,5102,3256,1297,1918,786],repeat_orders: [73,158,89,30,49,18]}) df df[repetition_rate] df[repeat_orders] / df[orders] df df[repetition_rate] df[repetition_rate].apply(lambda x: format(x, .2…

哈希表+字符串

一)知识回顾: 1)哈希表是什么?哈希表是存储数据的容器 2)哈希表有啥用?快速的查找某一个元素 3)什么时候使用哈希表?频繁的查找某一个数的时候&#xff0c;当我们快速查找某一个数的时候&#xff0c;不光要想到哈希表还需要想到二分查找&#xff0c;但是二分查找算法的局限性…

Linux——(第二章)Linux的目录结构

VMwear workstations下载及安装 Ubuntu server 18.04安装 VScode下载与安装 使用VS Code连接远程服务器 MobaXterm的下载安装及远程连接 Filezila的下载、安装与使用&#xff08;向服务器传输文件&#xff09; 目录 1.基本介绍 2.Linux目录结构 3.具体目录说明 4.补充 1.基…

从编程语言的角度来理解正则表达式

程序代码是对现实事物处理逻辑的抽象&#xff0c;而正则表达式&#xff0c;则是对复杂的字符匹配程序代码的进一步抽象&#xff1b;也就是说&#xff0c;高度简洁的正则表达式&#xff0c;可以认为其背后所对应的&#xff0c;是字符匹配程序代码&#xff0c;而字符匹配程序代码…

低代码:工业互联网从“学步”到“奔跑”的加速器

一、政策、技术合力推进&#xff0c;工业互联网发展提速 工业制造业曾经创造了我国的崛起神话&#xff0c;最近几年&#xff0c;随着新闻中一些老牌制造业厂商的闭幕&#xff0c;很多人都开始思考&#xff1a;未来工业会是什么样子&#xff1f; 放眼全球&#xff0c;各国对于工…

阿里云轻量应用服务器Linux-Centos7下Oracle19c的安装

初始环境&#xff1a;阿里云轻量应用服务器已经重置系统为CentOS7.3-64位 具体目标&#xff1a;安装Oracle Database 19c 目录 第一步&#xff1a;检查Linux系统版本第二步&#xff1a;下载Oracle19c的安装包第三步&#xff1a;下载Oracle19c的预安装包第四步&#xff1a;上传到…

react学习之路:TS报错-Its return type ‘Element[]‘ is not a valid JSX element

React报错之 Its return type ‘Element[]’ is not a valid JSX element 产生的原因&#xff1a; 1&#xff0c;函数组件返回的是Element数组&#xff0c;不是JSX元素。 2&#xff0c;如果组件返回的是JSX和null以外的值会提示类似’xxx’ cannot be used as a JSX componen…

023 - STM32学习笔记 - 扩展外部SDRAM(二) - 扩展外部SDRAM实验

023- STM32学习笔记 - 扩展外部SDRAM&#xff08;一&#xff09; - 扩展外部SDRAM实验 本节内容中要配置的引脚很多&#xff0c;如果你用的开发板跟我的不一样&#xff0c;请详细参照STM32规格书中说明对相关GPIO引脚进行配置。 先提前对本届内容的变成步骤进行总结如下&…

Breakpad交叉编译aarch64

原本是在mac os上编译的&#xff0c;但是会出现一些问题&#xff0c;因此还是开了台linux容器进行编译&#xff0c;本文可结合之前的linux下编译breakpad共同查看。 Linux下Breakpad编译_Edward.W的博客-CSDN博客https://blog.csdn.net/u013379032/article/details/130754480?…

day3 牛客TOP100:BM 21-30 二分法 二叉树

文章目录 二分法BM21 旋转数组的最小数字BM22 比较版本号力扣-旋转数组的查找力扣-两个非空链表逆序相加 二叉树BM23 二叉树的前序遍历BM24 二叉树的中序遍历BM25 二叉树的后序遍历BM26 求二叉树的层序遍历BM27 按之字形顺序打印二叉树BM28 二叉树的最大深度BM29 二叉树中和为某…

无涯教程-Android - Frame Layout函数

Frame Layout 旨在遮挡屏幕上的某个区域以显示单个项目&#xff0c;通常&#xff0c;应使用FrameLayout来保存单个子视图&#xff0c;因为在子视图彼此不重叠的情况下&#xff0c;难以以可扩展到不同屏幕尺寸的方式组织子视图。 不过&#xff0c;您可以使用android:layout_grav…

Unity——资产包(Asset Bundles)

对很多单机游戏来说&#xff0c;游戏的所有资源往往是与游戏本体一同发布的&#xff0c;资源部西药独立出来。但对于大型商业项目来说&#xff0c;游戏产品还需要再发布之后进行维护和更新&#xff0c;这就引出了Unity资产包的概念 一、资产包&#xff08;Asset Bundles&#x…

推荐几款常用测试数据自动生成工具(适用自动化测试、性能测试)

一、前言 在软件测试中&#xff0c;测试数据是测试用例的基础&#xff0c;对测试结果的准确性和全面性有着至关重要的影响。因此&#xff0c;在进行软件测试时&#xff0c;需要生成测试数据以满足测试场景和要求。本文将介绍如何利用测试数据生成工具来快速生成大量的测试数据…