linux启动流程、重置root密码、修复系统引导文件
1、linux启动流程
1.1 UEFi或BIOS初始化,运行POST开机自检
BIOS (Basic Input and Output System基本输入输出系统)就是一个程序,保存着有关计算机系统最重要的基本输入输出程序,系统信息设置,开机加电自检程序和系统启动自举程序等。其代码存储在主板的一颗ROM存储芯片上,ROM是只能读不能写的,这颗芯片上的BIOS程序,在主板出厂的时候,己经固化好了,所以不管断不断电,这个BIOS程序都会一直存储在这颗芯片上。
当我们修改了BIOS里面的某些设置时,这个修改的数据是存储在另外一颗RAM存储芯片上,RAM掉电后数据就会消失,所以主板上有一颗纽扣电池来给这个RAM供电,当这颗纽扣电池没电了,BIOS里面的设置项,就又恢复成出厂设置了。
POST:Power-On-Self-Test (加电自检),是BIOS程序中的一个主要功能,负责完成对CPU、主板、内存、硬盘子系统、显示子系统、串并行接口、键盘等硬件情况的检测。
对于一台计算机来讲,通电后第一件事件就是运行BIOS程序,BIOS程序最先做的,就是对硬件执行POST(加电自检),如果硬件自检不通过,会显示相应的错误,还会有相应的蜂鸣音。
UEFI 是传统 BIOS 的现代化替代品,它解决了 BIOS 在硬件支持、用户体验和安全性方面的诸多限制。提供图形化界面,支持鼠标操作,可以显示图形和品牌Logo,甚至支持高分辨率显示和本地化语言,用户体验更友好。
1.2 选择启动设备
硬盘
u盘
网络模式启动
1.3 引导加载程序bootloader
(1)BIOS 模式下的 Bootloader
BIOS找到硬盘后,只读取硬盘的第一个扇区(512字节),这个扇区叫做MBR。MBR里面包含了以下信息:
一小段引导代码(446字节)。
硬盘分区表(64字节)。
结束标志(2字节)。
centos7+默认采用grub2作为内核的引导管理器,grub2程序安装grub后,会在/boot/grub2/i386-pc/目录下生成boot.img和core.img文件,另外还包含文件系统类的模块等。
第一阶段 Bootloader:BIOS将MBR的446B加载到内存并执行。这段代码非常小,功能有限,它的主要任务是找到并加载第二阶段的Bootloader,也就是core.img。
在第二阶段 Bootloader会依次加载以下文件:
/boot/grub2/i386-pc/core.img#包含文件系统模块,并可以加载位于/boot/grub2/目录下的、功能完整的 GRUB 2 主程序和模块/boot/grub2/grub.cfg#加载该文件后可向用户提供操作系统的启动菜单(如果有多个内核或系统)当用户选择了要启动的操作系统菜单后,将根据grub2的配置文件找到内核文件vmlinuz-5.14.0-362.8.1.el9_3.x86_64和initramfs-5.14.0-362.8.1.el9_3.x86_64.img(临时的根文件系统镜像,内核需要它来挂载真正的根文件系统)文件并加载它,同时传递内核启动参数,包括根文件系统所在分区。
[!Important]
/boot/grub2/grub.cfg是根据命令grub2-mkconfig -o /boot/grub2/grub.cfg读取/etc/default/grub和/etc/grub.d/配置而生成的
(2)UEFI 模式下的 Bootloader
开机后,UEFI初始化时会去扫描一个特殊的分区——EFI系统分区 (ESP),UEFI固件内部集成了一个引导管理器会找到ESP分区中对应的**.efi** 文件路径。这个EFI文件包含了Bootloader的全部功能。它读取自己的配置文件,显示菜单,并加载操作系统内核。
1.4 内核启动和初始化阶段
到目前为止,内核已经被加载到内存并掌握了CPU的控制权,内核将initramfs解压的内容装入到tmpfs中。
initramfs为了尽早进入用户空间,它将init程序集成到了initramfs镜像文件中,这样就可以在initramfs装入tmpfs时直接运行init进程,而不用去找根文件系统下的/sbin/init。
内核在这个初始根文件系统中找到一个名为init的可执行文件(实际上是指向/usr/lib/systemd/systemd的链接)并执行它。此时,systemd以 PID 1 的身份首次出现,但这是在initramfs环境中。
[root@rhel93 ~]# mkdir /initramfs[root@rhel93 ~]# cd /initramfs/[root@rhel93 initramfs]# /usr/lib/dracut/skipcpio /boot/initramfs-5.14.0-362.8.1.el9_3.x86_64.img | zcat | cpio -id[root@rhel93 initramfs]# ll总用量12lrwxrwxrwx1root root78月2823:06 bin ->usr/bin drwxr-xr-x2root root748月2823:06 dev drwxr-xr-x13root root40968月2823:06 etc lrwxrwxrwx1root root238月2823:06 init ->usr/lib/systemd/systemd lrwxrwxrwx1root root78月2823:06 lib ->usr/lib lrwxrwxrwx1root root98月2823:06 lib64 ->usr/lib64 drwxr-xr-x2root root68月2823:06 proc drwxr-xr-x2root root68月2823:06 root drwxr-xr-x2root root68月2823:06 run lrwxrwxrwx1root root88月2823:06 sbin ->usr/sbin -rwxr-xr-x1root root46318月2823:06shutdowndrwxr-xr-x2root root68月2823:06 sys drwxr-xr-x2root root68月2823:06 sysroot drwxr-xr-x2root root68月2823:06 tmp drwxr-xr-x8root root818月2823:06 usr drwxr-xr-x3root root408月2823:06 var1.5 systemd执行initrd.target
systemd会启动initrd.target及其依赖的服务,包括挂载 /etc/fstab、从initramfs切换到真正的根文件系统。
[root@rhel93 system]# systemctl list-dependencies initrd.targetinitrd.target ○ ├─dracut-cmdline.service ○ ├─dracut-initqueue.service ○ ├─dracut-mount.service ○ ├─dracut-pre-mount.service ○ ├─dracut-pre-pivot.service ○ ├─dracut-pre-trigger.service ○ ├─dracut-pre-udev.service ○ ├─initrd-parse-etc.service ○ ├─systemd-pcrphase-initrd.service ● ├─basic.target ● │ ├─-.mount ○ │ ├─microcode.service ● │ ├─paths.target ● │ ├─slices.target ● │ │ ├─-.slice ● │ │ └─system.slice ● │ ├─sockets.target#切换根[root@rhel93 system]# systemctl list-dependencies initrd-switch-root.targetinitrd-switch-root.target ○ ├─initrd-cleanup.service ○ ├─initrd-switch-root.service ○ ├─initrd-udevadm-cleanup-db.service ● ├─plymouth-start.service ○ ├─plymouth-switch-root.service ● ├─systemd-journald.service ○ ├─initrd-fs.target ○ └─initrd-root-fs.target ○ └─systemd-repart.service[root@rhel93 initramfs]# cat ./usr/lib/systemd/system/initrd-switch-root.service[Unit]Description=Switch RootAssertPathExists=/etc/initrd-releaseDefaultDependencies=noWants=initrd-switch-root.targetAllowIsolate=yesOnFailure=emergency.targetOnFailureJobMode=replace-irreversibly[Service]Type=oneshotExecStart=systemctl --no-block switch-root /sysroot1.6 systemd执行默认target
此时systemd已经完成了根文件系统的切换,正式进入操作系统的初始化过程:
systemd会启动default.target及其依赖的sysinit.target初始化系统、basic.target准备操作系统、multi-user.target 下的本机与服务器服务、multi-user.target 下的/etc/rc.d/rc.local、multi-user.target下的getty.target及登录服务
[root@rhel93 ~]# systemctl list-dependencies default.targetdefault.target ● ├─atd.service ● ├─auditd.service ● ├─chronyd.service ● ├─crond.service ○ ├─insights-client-boot.service ● ├─irqbalance.service ● ├─kdump.service ● ├─libstoragemgmt.service ● ├─mcelog.service ○ ├─mdmonitor.service ● ├─NetworkManager.service......[root@rhel93 system]# cat /usr/lib/systemd/system/default.target[Unit]Description=Graphical InterfaceDocumentation=man:systemd.special(7)Requires=multi-user.target#表示要先执行multi-user.targetWants=display-manager.serviceConflicts=rescue.service rescue.targetAfter=multi-user.target rescue.service rescue.target display-manager.serviceAllowIsolate=yes[root@rhel93 system]# cat /usr/lib/systemd/system/multi-user.target[Unit]Description=Multi-User SystemDocumentation=man:systemd.special(7)Requires=basic.target#表示要先执行basic.targetConflicts=rescue.service rescue.targetAfter=basic.target rescue.service rescue.targetAllowIsolate=yes[root@rhel93 system]# cat /usr/lib/systemd/system/basic.target[Unit]Description=Basic SystemDocumentation=man:systemd.special(7)Requires=sysinit.target#执行sysinit.targetWants=sockets.target timers.target paths.target slices.targetAfter=sysinit.target sockets.target paths.target slices.target tmp.mount当default.target的所有单元都启动完毕,系统就准备就绪,显示登录界面(图形或命令行),等待用户使用。
2、linux systemd
2.1 systemd介绍
rhel7之前的系统都是使用init进程作为系统启动后的第一个进程,但是init有两个缺点:
启动时间长,因为init的进程是串行的,只有前一个启动完毕后一个进程才启动。
启动脚本复杂,以前的系统初始化需要加载很多脚本,依赖关系复杂,靠脚本自己处理。
而systemd的启动则是并行运行的,而且服务的启动配置文件统一语法,所以管理起来更方便。
从rhel 7 版本之后开始用 systemd 实现init进程,系统启动和服务器守护进程管理器,负责在系统启动或运行时,激活系统资源,服务器进程和其它进程。
systemd可以管理所有系统资源,不同的资源称为unit。可以使用man systemd.unit查看帮助
#查看systemd中的unit[root@rhel93 system]# systemctl -t helpAvailable unit types:service#文件扩展名为.service,用于定义系统服务mount#文件扩展名为.mount,定义文件系统挂载点swap#文件扩展名为.swap,用于标识swap设备socket#文件扩展名为socket,用于标识进程间通信用到的socket文件target#文件扩展名为.target,用于模拟实现“运行级别”,定义要系统初始化时要做的事device#文件扩展名为.device,用于定义内核识别的设备automount#文件扩展名为.automount,由systemd负责的自动挂载文件系统timer#定时器path#扩展名为.path,用于定义systemd监控的文件或目录,systemd使用notify监控文件的变化slice#进程组scope#不是由systemd启动的外部进程unit文件所在路径:
/usr/lib/systemd/system #每个服务最主要的脚本文件目录 /run/systemd/system/ #系统执行过程中所产生的服务脚本,比上面目录优先运行 /etc/systemd/system/ #管理员建立的执行脚本,比上面目录优先运行列出所有在内存中的单元:
# systemctl list-units命令也可以查看[root@rhel93 ~]# systemctl#查看状态为active的service,要查看所有的包括inactive的可以加上-a选项查看[root@rhel93 ~]# systemctl --type=serviceUNIT LOAD ACTIVE SUB DESCRIPTION atd.service loaded active running Deferred execution scheduler auditd.service loaded active running Security Auditing Service chronyd.service loaded active running NTP client/server crond.service loaded active running Command Scheduler dbus-broker.service loaded active running D-Bus System Message Bus输出字段说明:
| 字段 | 说明 |
|---|---|
| UNIT | 服务名称 |
| LOAD | 加载状态 loaded|not-found|bad-setting|error|masked |
| ACTIVE | 服务状态 active|reloading|inactive|failed|activating|deactivating |
| SUB | 详细状态,与 LOAD和ACTIVE列有关,具体可执行 systemctl --state=help 查看 |
| DESCRIPTION | unit描述信息 |
读取磁盘中存在的所有的service
[root@rhel93 ~]# systemctl list-unit-files --type=service -a2.2 service管理
管理服务常用命令
systemctl start nginx#启动服务:如果服务正在运行systemctl stop nginx#停止服务systemctl restart nginx#重启服务:先stop再startsystemctl reload nginx#重新加载服务配置文件systemctl status nginx#查看服务的运行状态systemctl is-active nginx#查看服务是否正在运行systemctlenablenginx#设置服务开机自启动,可以加上--nowsystemctl disable nginx#设置服务开机不自启动,可以加上--nowsystemctl is-enabled nginx#查看服务是否开机自启动systemctl list-unit-files#查看所有服务的开机自启动状态systemctl daemon-reload#重新载入更改的systemd配置文件systemctl mask nginx#禁用nginx服务,使之开机不自动启动且也不能手动启动systemctl unmask nginx#解除禁用效果服务运行状态说明:
#当我们使用systemctl status查看一个服务的运行状态时,有以下几种情况loaded#配置文件已经被加载active(running)#服务正在运行active(exited)#仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行。inactive(dead)#服务没有在运行enabled#服务被设定为开机自启动disabled#服务被设定为开机不自启动static#服务开机不自启动,但是可以被其他服务调用启动2.3 service unit文件格式
一般使用软件包安装的软件的启动配置文件在这个目录/usr/lib/systemd/system/下,systemd文件格式说明:
systemd unit文件通常是由三部分组成的[Unit]#一般定义的是通用选项,比如描述信息,依赖关系等[Service]#特定服务的类型,具体的启动关闭重启选项都在此部分配置[Install]#定义由systemctl enable和disable命令在实现服务开机自启和禁用时用到的一些选项Unit段常用说明:
Description#描述信息Documentation#说明文档的在线地址After#定义启动顺序,表示当前配置的服务应该晚于哪些服务之后启动Requires#依赖的其它units;强依赖,如果被依赖的units无法激活,当前unit也无法激活Wants#依赖到的其它units,弱依赖Conflicts#定义units间的冲突关系Service段常用说明:
Type#定义服务类型forking#需要父进程启动子进程的服务类型为forkingEnvironmentFile#环境配置文件PIDFile#定义PID文件路径ExecStart#指定启动服务命令绝对路径ExecStartPre#在启动之前运行的命令ExecStartPost#在启动之后运行的命令ExecStop#指定停止服务命令绝对路径ExecReload#指定重新加载服务的配置文件的命令绝对路径Restart#当该值为1时,则当此daemon服务意外终止后,会再次自动启动#####type值有7种,说明如下########simple#默认值, 执行ExecStart指定的命令,该命令的进程就是该服务的主进程;forking#以fork方式从父进程创建子进程,创建后父进程会立即退出;oneshot#与simple类似, 不过这个程序在工作完毕后就结束了,不会常驻在内存中;dbus#当前服务通过D-Bus启动;notify#在启动完成后会发送一个通知消息, 还需要配合NotifyAccess来让Systemd 接收消息idle#要执行这个daemon必须要所有的工作都顺利执行完毕, 这类daemon通常是开机到最后才执行的服务Install段常用说明:
WantedBy #被哪些服务依赖 Requiredby #被哪些服务依赖#例如nginx.server的Install中写了[root@rhel93 yum.repos.d]# sed -n '/Install/,$ p' /usr/lib/systemd/system/nginx.service[Install]WantedBy=multi-user.target#在设置nginx的开自启动时会在/etc/systemd/system/multi-user.target.wants目录下创建nginx.service的软链接[root@rhel93 yum.repos.d]# systemctl enable nginxCreated symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.修改完服务启动文件后,需要使用以下命令重载:
systemctl daemon-reload#重新载入更改的systemd配置文件2.4 systemd的运行级别
centos7开始,使用 target 来定义运行级别。当前默认使用的级别如下:
[root@rhel93 ~]# readlink /etc/systemd/system/default.target/usr/lib/systemd/system/multi-user.target查看所有的target
[root@rhel93 ~]# ls -l /usr/lib/systemd/system/run*target | grep -o "/usr.*"/usr/lib/systemd/system/runlevel0.target ->poweroff.target#关机/usr/lib/systemd/system/runlevel1.target ->rescue.target#救援模式,用于系统维护,禁止远程登录/usr/lib/systemd/system/runlevel2.target ->multi-user.target#多用户模式,文本界面/usr/lib/systemd/system/runlevel3.target ->multi-user.target /usr/lib/systemd/system/runlevel4.target ->multi-user.target /usr/lib/systemd/system/runlevel5.target ->graphical.target#多用户模式,图形界面/usr/lib/systemd/system/runlevel6.target ->reboot.target#重启修改默认级别
[root@rhel93 ~]# systemctl set-default multi-user.target[root@rhel93 ~]# systemctl get-defaultmulti-user.target3、重置root密码
3.1 使用单用户模式重置密码
方法一:
启动时按任意键暂停启动 按e键进入编辑模式 将光标移动linux 开始的行,添加内核参数 rd.break 按ctrl+x启动mount–o remount,rw /sysrootchroot/sysrootpasswdroot#如果SELinux是启用的,才需要执行下面操作,如查没有启动,不需要执行touch/.autorelabelexitreboot方法二:
启动时任意键暂停启动 按e键进入编辑模式 将光标移动linux 开始的行,添加 rwinit=/sysroot/bin/sh 按ctrl+x启动chroot/sysrootpasswdroot#如果SELinux是启用的,才需要执行下面操作,如查没有启动,不需要执行touch/.autorelabelexitreboot3.2 使用光盘重置密码
设置系统通过光盘启动:
选择troubleshooting
选择rescue a Red Hat Enterprise Linux system
按照以下操作进行密码重置
调整系统从硬盘启动
4、系统引导文件的修复
4.1 误删grub.cfg文件,但还未重启系统
(1)模拟将文件删除
[root@rhel93 ~]# ls /boot/grub2/device.map fonts grub.cfg grubenv i386-pc locale[root@rhel93 ~]# rm -f /boot/grub2/grub.cfg(2)恢复该文件
[root@rhel93 ~]# grub2-mkconfig -o /boot/grub2/grub.cfg4.2 误删grub.cfg文件,已经重启系统
请先查看/所在分区:
[root@rhel93 ~]# df -h /文件系统 容量 已用 可用 已用% 挂载点 /dev/mapper/rhel-root 97G2.5G 95G3% /如果误删grub.cfg文件,重启系统时会进入如下界面
先使用如下方式让此次系统正常启动
grub>setroot=(hd0,msdos1)#指定boot分区位置#hdn 便是boot分区在那个硬盘上#msdosn在那个分区# 指定内核文件, 只读挂载/设备grub>linux16 /vmlinuz-5.14.0-362.0.1.el9_3.x86_64 roroot=/dev/mapper/rhel-root grub>initrd16 /initramfs-5.14.0-362.8.1.el9_3.x86_64.img grub>boot注意: 以上步骤只能完成本次引导, 系统重启后仍然需要手动引导
#进入系统后执行以下命令,恢复grub.cfg文件[root@rhel93 ~]# grub2-mkconfig > /boot/grub2/grub.cfg4.3 误删/boot/grub2/目录,已经重启系统
删除/boot/grub2/目录,重启系统后出现如下界面
此时调整系统启动方式通过光盘进入救援模式
选择troubleshooting
选择rescue a Red Hat Enterprise Linux system
按照如下步骤操作
调整系统从硬盘启动
启动成功后即可正常登陆
4.4 误删/boot/目录下的文件,已经重启系统
该种情况下和4.3的操作一样都需要通过光盘启动,不同点在于增加了需要重新安装内核和initramfs文件的包的步骤:
#模拟文件被删除[root@rhel93 ~]# rm -rf /boot/*设置使用光盘启动后输入如下命令:
最后使用硬盘启动即可。
