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。
- 可能会用到的资料有如下所示,下载链接见文末:
- 《鸟哥的Linux私房菜 基础学习篇 第四版》1
- 《鸟哥的Linux私房菜 服务器架设篇 第三版》2
- 《韩顺平_2021图解Linux全面升级》3
22.1 Linux7启动流程介绍
22.1.1 Linux7启动流程
首先来介绍一下CentOS7的启动流程:
【参考1】CSDN博文“centos7 开机启动流程”。
【参考2】稀土掘金文章“一文快速看懂 Centos7 系统的启动过程(配思维导图)”。
下面来对上图做出一些注释:
- 第一阶段:硬件引导启动
- Power On:上电。
- BIOS:查找启动介质时会选择:光驱启动(CDROM)、USB启动、硬件启动(HDD)。
- 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”开始)的介绍:
一些注意点:
- 内核解压并自检:若内核有问题,跑不起来。
- 由虚拟根目录切换回磁盘根目录:这个时候磁盘就找到了。
- 调用muliti-user.target:表示“多用户模式”。
- 启动本级别对应的服务:比如本级别定义的自启服务,可以使用指令
systemctl
来更改这些要自启的服务。- 调用/etc/rc.d/rc.local:定义开机后需要自启的自定义脚本。
最关键的第四阶段(“多用户模式”作为演示示例):
- 执行默认target配置文件
/etc/systemd/system/default.target
(这是一个软链接,与默认运行级别有关)。- 并发执行
sysinit.target
来初始化系统和basic.target
来准备操作系统。- 并发启动
multi-user.target
下的本机与服务器服务,并检查/etc/rc.d/rc.local
文件是否有用户自定义脚本需要启动。- 最后执行multi-user下的
getty.target
及登录服务,检查default.target
是否有其他的服务需要启动。
显然在上述“调用systemd”启动的过程中调用了很多系统配置文件,下面简单对这些文件的依赖关系做出示意:
如上图所示:
/etc/systemd/system/default.target
指向了/lib/systemd/system/
目录下的graphical.target
或multiuser.target
。而graphical.target
依赖multiuser.target
,multiuser.target
依赖basic.target
,basic.target
依赖sysinit.target
,所以倒过来执行。
最后是chatgpt的简单总结:
- BIOS/UEFI 启动:计算机首先执行 BIOS 或 UEFI 中的引导程序,查找可引导的设备。一般来说,它会查找磁盘或其他存储设备以加载引导加载程序。
- 引导加载程序(GRUB2):GRUB2 是 CentOS 7 默认使用的引导加载程序。GRUB2 负责显示引导菜单,其中列出了可用的内核选项。
- 加载内核和 initramfs:一旦用户选择内核选项,GRUB2 会加载指定的内核文件(vmlinuz),同时加载相关的 initramfs(初始化 RAM Disk)。initramfs 是一个临时文件系统,包含了内核启动所需的文件和驱动程序。
- 内核初始化和启动 init:内核初始化时,它会检测硬件、加载驱动程序并设置系统参数。然后,内核启动第一个用户空间进程,这通常是 systemd 初始化进程。
- systemd 初始化:systemd 是 CentOS 7 默认使用的初始化系统,它负责启动和管理系统的各种服务。systemd 启动一系列的目标(target),每个目标包含要同时启动的一组服务。
- 运行级别(Runlevel)切换:在过去的 SysVinit 系统中,运行级别定义了系统在不同模式下启动的配置。在 CentOS 7 中,systemd 引入了目标(target)的概念,取代了运行级别。
- 启动服务和进程:在所选的目标中,systemd 启动相关的服务和进程。这可能涉及网络、文件系统、登录管理、时间同步等各种服务。
- 启动显示管理器(如果有):如果您的系统配置了图形用户界面(GUI),systemd 可能会启动 X Window 系统或其他显示管理器,显示登录界面。
- 用户登录:最终,系统会显示登录界面,用户可以通过图形界面或终端登录。
总之,CentOS 7 的启动流程涉及硬件初始化、加载内核、初始化 RAM Disk、启动用户空间、systemd 初始化和服务启动等步骤。每个步骤都是为了确保系统能够成功启动并准备好接受用户登录和任务执行。
22.1.3 systemd概述
本小节简单介绍一下systemd初始化系统。systemd(system daemon)是Linux下的一种init软件,开发目标是提供更优秀的框架以表示系统服务间的以来关系,并依此实现系统初始化时服务的并行启动,同时达到降低Shell系统开销的效果,最终代替了之前的System V与BSD风格的init程序。与多数发行版使用的System V风格的init相比,systemd采用了以下的新技术:
- 采用Socket激活式与总线激活式服务,以提高相互依赖的各服务的并行运行性能。
- 用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 12月 9 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 4月 5 22:10 runlevel0.target -> poweroff.target
lrwxrwxrwx. 1 root root 13 4月 5 22:10 runlevel1.target -> rescue.target
lrwxrwxrwx. 1 root root 17 4月 5 22:10 runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 4月 5 22:10 runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 4月 5 22:10 runlevel4.target -> multi-user.target
lrwxrwxrwx. 1 root root 16 4月 5 22:10 runlevel5.target -> graphical.target
lrwxrwxrwx. 1 root root 13 4月 5 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的原则就是只保留与启动相关的部分,剔除其余所有部分,思路如下(如下图):
- 创建新磁盘。
在现有的Linux系统(centos7.6)上添加一块磁盘/dev/sdb,并添加两个分区:启动分区/boot
、根分区/
,然后将其格式化,新磁盘创建完成。注:需要明确的是,现在加的这个磁盘在现有的Linux系统中是
/dev/sdb
,但是,当我们把东西全部设置好时,要把这个磁盘拔除并放在新系统上,就是新系统的/dev/sda
。
- 制作启动盘。
本步骤的目的就是将/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
。
- 创建新的虚拟机min-linux。
在VMware创建一个新的虚拟机,然后移出默认分配的磁盘,将上述制作好的启动盘挂载到该新系统上,即可启动。- 添加指令。
虽然在“制作启动盘”时已经添加了库文件和Shell解释器,但几乎所有指令都存放在/bin
、/sbin
目录下,并且这些指令加在一起异常庞大,所以只有最基本的指令(如cd
)添加到了启动盘中。若想使用其他指令(如ls
、reboot
等),就需要额外添加指令。以上步骤完成,我们的自制Linux就完成,创建一个新的Linux虚拟机,将其磁盘指向我们创建的磁盘,启动即可。
22.3 操作步骤
步骤1:创建新磁盘
本步骤的目的是在原本的虚拟机(CentOS7.6)下创建一块新的磁盘,具体的步骤如下:
- VMware添加新磁盘。
- 磁盘分区。
- 磁盘格式化。
1. VMware添加新磁盘
首先将旧虚拟机关机,然后按照下面的步骤在VMware添加新磁盘,最后开启旧虚拟机。我们先假设这块磁盘的大小为20G。
开机后,使用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.
正在同步磁盘。
分区完成后可再次查看磁盘情况,可以看到已经有了分区sdb1
、sdb2
,但都没有挂载点:
[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
磁盘中所有的分区(sdb1
、sdb2
)都进行格式化,是为了生成各个分区的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的启动盘,具体的步骤如下:
- 挂载磁盘。
- 安装grub并拷贝/boot。
- 修改
/mnt/boot/grub2/grub.cfg
文件。- 创建根文件系统。
- 拷贝库文件和Shell解释器。
1. 挂载磁盘
首先在旧虚拟机的系统下创建新虚拟机要用的引导分区目录/mnt/boot
、根分区目录/mnt/sysroot
,然后将sdb1
、sdb2
分别挂载到这两个分区上:
注:在前面“目录结构”一章中就提到,
/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引导加载程序”的配置文件,用于配置操作系统的启动选项和引导过程中的各种设置,如选用哪个内核、启动模式等。内核和启动模式等一系列内容都可以和旧虚拟机保持相同,我们并不关心,但是“启动盘”和“根目录盘”应该调整为新创建的sdb1
、sdb2
,而不是旧虚拟机的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
为根分区,具体修改方法如下:
- 将
sda1
的UUID换成sdb1
的UUID,将sda3
的UUID换成sdb2
的UUID。- 在
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上,即可开机。具体的步骤如下:
- 创建min-linux虚拟机。
- 移除默认磁盘并添加启动盘。
- 开机测试。
1. 创建min-linux虚拟机
在VMware菜单栏选择“文件”–>“新建虚拟机”,然后按照下图所示进行操作:
2. 移除默认磁盘并添加启动盘
在创建min-linux时,VMware的引导程序显然创建了默认硬盘,下面我们移出这个默认的硬盘,并将上一小节制作好的启动盘添加到当前系统中。如下图所示操作:
3. 开机测试
上述硬盘更换完成后即可开机测试指令,如下所示则证明系统可以正常运行:
测试完成后,发现虽然系统可以正常运行,但是居然来连ls
指令都无法使用,所以下面如果有需求的话,还可以在向min-linux添加一些指令。
步骤4(选做):添加额外的指令
由于Linux系统的指令一般都存放在/bin
、/sbin
目录下,所以向min-linux添加指令的思路很简单:
- 关闭min-linux,开启旧虚拟机。
- 将
sdb2
重新挂载到根分区新虚拟机的根分区/mnt/sysroot
上,然后拷贝旧虚拟机/bin
、/sbin
目录下的指令到对应的/mnt/sysroot/bin
、/mnt/sysroot/sbin
目录下。- 关闭旧虚拟机,开启min-linux,即可运行新指令。
注:不要一股脑将所有指令都拷贝过去,因为某些指令文件很大,制作min-linux的初衷只是能运行的最小linux系统,这样的系统通常是运行在低功耗的物联网小模块中,并不要求该系统有很好的人机交互功能。
下面是在旧虚拟机上的操作(仅拷贝了ls
、reboot
、systenctl
):
[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后,新添加指令的运行情况示意图和代码块注释:
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的大小是真的小!!
《鸟哥的Linux私房菜 基础学习篇 第四版》 ↩︎
《鸟哥的Linux私房菜 服务器架设篇 第三版》 ↩︎
《韩顺平_2021图解Linux全面升级》 ↩︎