第三周作业
1. CPU分片机制与CPU队列:简述 CPU 分片机制(时间片)的原理与它的优缺点。什么是就绪队列(Ready Queue)与等待队列(Wait Queue)?运行队列(Run Queue)与过期队列(Expired Queue)之间有何关系?
CPU 分片机制就是把 CPU 时间切成一小段一小段的时间片(time slice / quantum),操作系统调度器按顺序把时间片分给各个进程/线程运行。当一个进程获得 CPU 时,它最多只能连续运行一个时间片。如果时间片用完而进程仍未结束或未主动让出 CPU,时钟中断会触发调度器,强制把 CPU 分配给下一个就绪进程。被抢占的进程重新排回就绪队列,等待下一次调度。这种机制保证了多道程序在微观上轮流执行,在宏观上表现为并发运。
优点:公平性:每个就绪进程都能定期获得 CPU 时间,避免某个进程长时间独占 CPU。交互响应性:短时间片能让交互式任务(如用户输入)快速得到响应,用户感觉系统流畅。实现简单:基于时钟中断的抢占式轮转调度,易于理解和实现。避免长作业独占 CPU:即使某个进程很耗 CPU,也不会一直阻塞其他进程。
缺点:上下文切换开销:频繁的进程切换需要保存和恢复寄存器、刷新 TLB、切换内存映射等,会消耗大量 CPU 时间,降低系统吞吐量。时间片大小难权衡:时间片太短会导致切换开销占比过大;时间片太长则退化为先来先服务,失去并发性和响应性。对不同类型的进程不够友好:CPU 密集型和 I/O 密集型进程不加以区分时,I/O 密集型进程可能经常用不完时间片就阻塞,而 CPU 密集型进程则可能占用过多资源,需要更精细的调度策略来弥补。
就绪队列与等待队列
-
就绪队列(Ready Queue)
存放所有已经准备好运行、只等待分配 CPU 的进程。这些进程的上下文(如程序计数器、寄存器、内存映射等)已保存在内存中,只要调度器选中它,就可以立即上 CPU 执行。就绪队列通常按某种优先级或时间顺序组织(如多级反馈队列),是调度器的直接操作对象。 -
等待队列(Wait Queue)
存放由于等待某些事件发生而主动阻塞的进程,这些事件包括 I/O 完成、信号量释放、接收到信号、子进程结束等。处于等待队列的进程不消耗 CPU,也不会被调度。当所等待的事件发生后,操作系统会将相应进程从等待队列移出,转入就绪队列,让其重新参与竞争 CPU。 -
运行队列(Run Queue)与过期队列(Expired Queue)的关系
-
运行队列(Run Queue)
在 Linux 内核中,每个 CPU 都有一个运行队列(runqueue),用来管理该 CPU 上所有可运行的进程。它本身不是单一链表,而是包含两个优先级数组:active(活跃队列)和expired(过期队列)。所有可运行进程都会被放入这两个数组之一。运行队列中放的是当前可运行的任务,也就是调度器此刻可以选择执行的进程/线程。 -
过期队列(Expired Queue)
指expired优先级数组,专门存放那些当前时间片已耗尽但仍需要继续运行的进程。当一个进程在active队列中用完时间片后,调度器会重新计算它的时间片和优先级,然后把它从active移到expired队列末尾。 -
二者的关系
-
同属一个运行队列:
active和expired是同一个runqueue里的两个子结构,分别存放时间片尚未用完和已用完的进程。 -
交替切换,避免全局重算:调度器总是从
active队列中选取进程执行。当active队列为空(即所有进程都用完了时间片),调度器只需交换active和expired的指针——原来的expired成为新的active,原来的active变为新的expired(此时为空)。这样无须一次性遍历并重算所有进程的时间片,实现了 O(1) 时间复杂度的调度。可以理解为运行队列:当前这一轮“正在比赛”的选手。过期队列:这一轮时间用完,等下一轮再上场的选手。
-
2. 进程与线程的核心区别及运维关注点:从定义、开销、通信、场景四个维度对比进程与线程的差异。在日常运维和故障排查中,为什么需要关注线程?请写出 4 个常用的线程排查工具,并举例说明哪些中间件的哪些配置参数与线程数密切相关。
| 维度 | 进程(Process) | 线程(Thread) |
|---|---|---|
| 定义 | 操作系统进行资源分配的基本单位 | CPU 调度执行的基本单位,是进程内的执行流 |
| 资源 | 拥有独立的地址空间、文件句柄、内存资源等 | 共享所属进程的地址空间和大部分资源 |
| 开销 | 创建、销毁、切换开销较大 | 创建、销毁、切换开销较小 |
| 通信 | 通过 IPC:管道、消息队列、共享内存、socket 等,成本较高 | 直接读写共享内存即可,但要加锁/同步,避免竞态 |
| 隔离性 | 强,某个进程崩溃通常不影响其他进程 | 弱,一个线程异常可能拖垮整个进程 |
| 适用场景 | 需要强隔离、高稳定性的场景 | 高并发、轻量任务、需要频繁切换的场景 |
因为很多线上服务(尤其是 Java 应用、Tomcat、Kafka、Elasticsearch 等)采用多线程模型。CPU 飙高、线程池耗尽、死锁、GC 异常、请求阻塞等问题往往发生在线程层面,仅查看进程无法定位根因,因此需要结合 top -H、ps -eLf、jstack、pstack/gstack 等工具进行线程级分析。常见情况包括:
-
线程池耗尽
- 请求进来了,但业务线程都在等待,导致接口超时、系统假死。
-
死锁 / 线程阻塞
- 线程互相等待锁,服务整体卡住,但进程还活着。
-
CPU 飙高
- 往往是某个线程死循环、忙等、频繁 GC 相关线程占用高。
-
线程泄漏
- 线程不断创建但不回收,最终导致上下文切换严重、内存压力增大。
-
I/O 等待堆积
- 大量线程卡在数据库、RPC、磁盘、网络上,表现为吞吐下降、响应时间变长。
| 工具 | 作用 | 常见用途 |
|---|---|---|
top -H -p <PID> |
查看某个进程内所有线程的 CPU、内存等使用情况 | 找出高 CPU 的线程 |
ps -eLf(或 ps -T -p <PID>) |
查看系统或指定进程的线程列表、LWP(线程 ID)和线程数量 | 统计线程数、确认线程是否异常增长 |
jstack <PID> |
导出 Java 线程栈 | 分析死锁、阻塞、高 CPU、线程池耗尽等问题 |
pstack <PID>(或 gstack <PID>,视发行版而定) |
查看原生(C/C++)程序的线程调用栈 | 分析 Nginx、MySQL、Redis 等非 Java 程序的线程状态 |
| 中间件 | 配置参数 | 作用 |
|---|---|---|
| Nginx | worker_processes、worker_connections |
决定工作进程数量及每个工作进程可处理的连接数,影响整体并发能力 |
| Tomcat | maxThreads、minSpareThreads |
控制 HTTP 请求处理线程池大小太少会请求堆积,太多会导致频繁上下文切换和 OOM |
| Spring Boot(嵌入式 Tomcat) | server.tomcat.threads.max、server.tomcat.threads.min-spare |
配置 Web 服务线程池 |
| Java 线程池 | corePoolSize、maximumPoolSize、queueCapacity |
控制线程池核心线程、最大线程及队列容量 |
| MySQL | max_connections、thread_cache_size |
每个客户端连接通常对应一个服务线程,线程缓存可减少线程创建开销 |
| Redis | io-threads、io-threads-do-reads(Redis 6+) |
配置 I/O 线程数量,提高网络 I/O 处理能力 |
| Kafka | num.network.threads、num.io.threads |
控制网络线程和 I/O 线程数量 |
| Elasticsearch | thread_pool.*(如 thread_pool.search.size、thread_pool.write.size) |
控制各类线程池大小,影响查询、写入等性能 |
3. 进程创建机制与1号进程:简述在 Linux 中创建进程的核心逻辑(复制现有进程与加载程序映像过程)。Linux 系统的第一号进程是什么?
一、Linux 中创建进程的核心逻辑
Linux 不会“凭空”创建一个新进程,而是采用**“复制现有进程 + 加载新的程序映像”的方式创建新进程。整个过程主要包括两个核心步骤:fork()(或 clone())** 和 exec()。
1. 第一步:复制现有进程(fork)
当一个程序需要启动另一个程序时,会调用:fork() 的作用是创建一个与当前进程几乎完全相同的子进程。
创建后:
-
原来的进程称为父进程(Parent Process)
-
新创建的进程称为子进程(Child Process)
- 父子进程具有以下特点:
-
拥有不同的 PID(进程号)
-
子进程记录父进程的 PPID(父进程号)
-
初始时拥有几乎相同的代码、数据、环境变量、文件描述符等资源
-
采用写时复制(Copy On Write,COW) 技术,共享内存页,只有当某一方修改数据时,才真正复制对应内存页,从而减少内存占用并提高创建效率。
2. exec() 系列 —— 加载新程序映像
子进程通常在 fork() 后立即调用 execve()(或其他 exec 变体),用全新程序替换当前进程的地址空间:
- 清除原有内存映射,加载新的可执行文件到内存;重置堆、栈、数据段,设置新的入口点;保留大部分内核属性(如 PID、文件描述符、进程关系),仅替换用户态映像。
-
这种设计完美分离了“生成新执行上下文”和“装载新程序”两个概念,衍生出
posix_spawn()等封装,也方便实现 shell 重定向、管道等机制。fork()负责“生出一个新进程”exec()负责“让这个进程运行另一个程序” -
二、Linux 的第一号进程
-
Linux 内核启动完成后,会创建第一个用户态进程,即 PID 为 1 的初始化进程(过去通常是
init,现代发行版多为systemd或OpenRC等)。1号进程的特殊职责:
- 系统初始化
- 挂载文件系统
- 初始化设备
- 设置主机环境
- 启动和管理系统服务
- 启动 SSH、网络、日志、数据库、Web 服务等
- 管理 Service、Socket、Timer 等 Unit
- 管理进程生命周期
- 启动、停止、重启服务
- 监控服务状态
- 自动拉起异常退出的服务(按配置)
- 回收孤儿进程
- 当父进程退出时,孤儿进程会被 PID 1 接管(收养),由其负责后续资源管理。
- 系统关机与重启
- 协调关闭各项服务
- 执行关机、重启流程
4. 进程状态及“不可能发生的切换”:在使用 ps aux 命令时,STAT 列中常见的进程状态字符(D, R, S, T, Z, l, +)分别代表什么?另外,在进程状态转换中,哪两种切换是不可能发生的?为什么?
| 状态 | 含义 | 说明 | 运维关注点 |
|---|---|---|---|
| R (Running/Runnable) | 运行或就绪状态 | 正在 CPU 上运行,或已经具备运行条件,等待 CPU 调度 | CPU 使用率高时,可能会看到大量 R 状态进程 |
| S (Sleeping) | 可中断睡眠 | 等待事件(如网络、键盘输入、定时器、I/O 等),收到信号可以被唤醒 | 最常见状态,大多数后台服务平时都处于 S |
| D (Uninterruptible Sleep) | 不可中断睡眠 | 通常等待磁盘、NFS、存储等 I/O 完成,不能响应普通信号 | 大量 D 状态通常意味着磁盘、存储或网络文件系统故障 |
| T (Stopped/Traced) | 停止状态 | 被 SIGSTOP、SIGTSTP 暂停,或正在被调试(如 gdb) |
常见于调试程序或执行 kill -STOP PID |
| Z (Zombie) | 僵尸进程 | 子进程已退出,但父进程未调用 wait()/waitpid() 回收资源 |
数量过多说明程序存在缺陷,应重点排查父进程 |
| l(小写 L) | 多线程进程 | 表示该进程是多线程(Multi-threaded),通常使用 CLONE_THREAD 创建线程 |
Java、MySQL、Tomcat 等服务经常出现该标记 |
| + | 前台进程组 | 表示进程属于当前终端的前台进程组 | 常见于 Shell 中直接运行的程序,如 vim、top |
就绪态 → 阻塞态(Ready → Blocked)
原因:进程必须先获得 CPU 并实际执行,才能通过系统调用(如 read、sem_wait)主动让自己进入阻塞。处于就绪态的进程根本没有运行,无法发出阻塞请求,因此不可能直接从就绪态跳转到阻塞态。正确路径:就绪 → 运行 → 阻塞。
阻塞态 → 运行态(Blocked → Running)
原因:当阻塞进程等待的事件发生时,它只是被唤醒并放入就绪队列,随后必须等待操作系统的调度器选中它,才能被分配 CPU。所以它必须先回到就绪态,不能直接抢占运行。正确路径:阻塞 → 就绪 → 运行。
在 ps 的语境下:
- D → T:不可能直接发生,因为 D 状态下进程处于不可中断睡眠,不响应停止信号,必须等待 I/O 完成后才能被暂停。
- Z → R(或其他可执行状态):不可能发生,因为僵尸进程已经结束执行,仅保留退出信息等待回收,不会再次运行。
5. 特殊的进程与内存异常:什么是僵尸进程与孤儿进程?它们是如何产生的,应当如何回收与清理?当系统发生 OOM (Out Of Memory) 时,内核会采取什么应对策略?在哪个系统日志中可以观察到 OOM 记录?
一、僵尸进程与孤儿进程
| 类型 | 定义 | 产生原因 | 回收与清理 |
|---|---|---|---|
| 僵尸进程 | 子进程已终止,但父进程尚未调用 wait()/waitpid() 读取其退出状态,内核为该子进程保留的 task_struct 一直存在,进程状态显示为 Z (Zombie)。 |
父进程没有处理 SIGCHLD 信号,或者父进程因代码 bug 未回收子进程。 |
1. 父进程主动调用 wait() 或 waitpid();2. 父进程设置 signal(SIGCHLD, SIG_IGN) 显式忽略子进程退出信号(内核会直接回收);3. 如父进程无法正常回收,杀掉父进程——僵尸进程会变成孤儿,被 init(PID 1) 收养并自动回收。 |
| 孤儿进程 | 父进程先于子进程终止,子进程变成孤儿,被 init 进程(PID 1)收养。 |
父进程退出,子进程仍在运行。 | 无需手动干预:init 进程会自动调用 wait() 回收这些子进程。孤儿进程本身不消耗额外内核资源,仅短暂处于被接管状态。 |
关键区别:僵尸已死但残留信息,占用 PID 和进程表项;孤儿仍存活且有父进程接管。僵尸过多会导致 PID 耗尽,系统无法创建新进程。
二、OOM(Out of Memory)时内核的应对策略
当系统内存(包括 swap)极度匮乏,连内核都无法分配内存时,会触发 OOM Killer 机制:
-
选择牺牲进程
内核调用out_of_memory()函数,基于每个进程的oom_score和oom_score_adj计算出一个“坏”分数。分数越高的进程越容易被选中。通常影响因素包括:-
内存占用总量(越高越容易被杀)
-
CPU 使用时间(保护运行较久的进程)
-
进程的
oom_score_adj手动调整值(如-1000可完全免杀) -
是否为 root 进程、是否占据终端等
-
-
执行杀死操作
内核向选中进程发送SIGKILL信号,强制终止并释放其占用的内存。之后会打印详细报告,列出被杀进程的内存信息、系统内存统计等。 -
连锁反应控制
在某些内核版本中,为避免频繁 OOM,可配置panic_on_oom参数直接触发内核 panic,或oom_kill_allocating_task直接杀死当前触发内存分配的进程。
三、OOM 记录的查看位置
OOM 事件会记录在内核环形缓冲区中,可通过下列方式查看:
| 查看方法 | 说明 |
|---|---|
dmesg | grep -i "out of memory" |
直接读取内核缓冲区,通用性最强 |
journalctl -k | grep -i oom |
在 systemd 系统中查看内核日志 |
/var/log/messages |
RHEL/CentOS 等系统的系统日志 |
/var/log/syslog |
Debian/Ubuntu 等系统的系统日志 |
/var/log/kern.log |
某些发行版独立的内核日志 |
日志中会包含形如 Out of memory: Kill process <PID> (<name>) 的条目,以及详细的 oom-killer 调用栈和被杀进程的内存统计。
6. 进程间通信 (IPC) 的概念与方式:什么是进程间通信 (IPC)?请列举 Linux 中常见的三种 IPC 方式(如管道、消息队列、套接字等),并简要说明其各自特点。
IPC(Inter-Process Communication,进程间通信) 是指不同进程之间交换数据、传递信息、实现同步与协作的一系列机制。由于 Linux 中每个进程拥有独立的虚拟地址空间,一个进程不能直接访问另一个进程的内存,因此必须借助 IPC 机制进行通信。
| IPC 方式 | 特点 |
|---|---|
| 管道 (Pipe) | • 半双工(数据只能单向流动),通常用于父子进程或有亲缘关系的进程间通信 • 采用字节流形式,无消息边界,读写端固定 • 命名管道 (FIFO) 突破亲缘关系限制,可通过文件路径访问 • 生命周期随进程,内核缓冲区有限,同步阻塞式读写 |
| 消息队列 (Message Queue) | • 消息有固定边界,发送/接收以消息为单位,不依赖字节流 • 支持多对多通信,按消息类型/优先级排序 • 消息存放在内核,进程退出后仍存在(随系统持续) • 异步通信,发送方无需等待接收方准备好 |
| 套接字 (Socket) | • 最通用的 IPC,支持本地进程间(Unix Domain Socket)和跨网络主机通信 • 全双工,数据双向传输 • 提供流式 (TCP) 和数据报 (UDP) 两种模型,可带外数据 • 接口标准化,方便异构系统交互,但开销相对前两者较大 |
7. 作业控制(Job Control)与特殊符号:在 Linux 作业控制中,如何将前台任务放到后台暂停?如何让其在后台继续运行或调回前台?fg 命令中 % 符号的含义是什么?%+ 和 %- 分别代表什么?
-
将前台任务放到后台暂停
在终端中运行命令时,按Ctrl + Z会向前台进程组发送SIGTSTP信号,使该任务暂停并被放入后台。此时屏幕上会显示类似[1]+ Stopped command,表示作业编号和状态。 -
让暂停任务在后台继续运行
使用bg命令可将当前或指定作业在后台恢复运行,相当于发送SIGCONT信号并让其继续在后台执行。 -
将后台任务调回前台
使用fg命令可以将后台任务(无论是暂停还是在运行)调回终端前台继续 -
fg # 将当前作业调回前台
fg %2 # 将作业 2 调回前台 -
fg命令中%符号的含义%是作业标识符前缀,用来引用作业控制列表中的某个作业。fg %n中的%n表示作业编号n。此外,%后还可以跟字符串匹配命令名(如fg %vim)、+、-等。 -
%+与%-的含义-
%+或%%代表当前作业:最近被暂停或后台启动的那个作业。 -
%-代表前一个作业:在当前作业之前被操作的作业。
在jobs命令的输出中,当前作业旁会标注+,前一个作业标注-。使用fg或bg不指定参数时,默认操作%+。
-
8. 进程优先级调整与 CFS 调度算法:Linux 进程的 nice 值与 PR(Priority)值的取值范围分别是多少?普通进程的 CFS(完全公平调度)算法的工作原理是什么?nice 值每降低 1,权重有何变化?请说明如何使用 renice 修改一个运行中进程的 nice 值。
Linux 是抢占式多任务操作系统,当多个进程同时需要 CPU 时,内核调度器会根据**优先级(Priority,PR)**决定哪个进程优先获得 CPU。PR(Priority):调度优先级;NI(Nice):用户可调整的优先级。
一、nice 值与 PR 值的取值范围
-
nice 值:用户空间可调整的友好度,范围 -20(最高优先级)至 +19(最低优先级),默认值为 0。
-
PR(Priority)值:
top或ps -l中显示的优先级。-
对于 普通进程,
PR = 20 + nice,因此范围是 0(nice -20)至 39(nice +19)。 -
实时进程的 PR 显示为
rt或负数。 -
在内核内部,普通进程对应的静态优先级(
static_prio)是 100(nice -20)至 139(nice +19)。
-
二、普通进程的 CFS 完全公平调度算法工作原理
CFS(Completely Fair Scheduler)的目标是让所有普通进程公平地共享 CPU 时间,核心原理如下:
-
虚拟运行时间 (vruntime):每个进程维护一个
vruntime,代表它的“虚拟运行时间”。-
vruntime = 实际运行时间 × (1024 ÷ 权重) -
权重越高的进程,
vruntime增长越慢,相当于“享受时间”越慢。
-
-
红黑树管理:所有可运行进程按
vruntime插入一棵红黑树,调度器每次选择最左节点(vruntime 最小)的进程运行。 -
时间片与周期:
-
CFS 定义一个目标延迟(如 6ms),在该周期内保证所有可运行进程至少执行一次。
-
每个进程分配的时间片与它的权重成正比:
时间片 = 目标延迟 × (进程权重 / 总权重)。 -
若可运行进程过多,每个进程的时间片会有一个最小值(如 0.75ms),防止切换开销过大。
-
-
抢占与唤醒修正:
-
当新进程加入或休眠进程被唤醒时,会重新计算其
vruntime(通常取红黑树中最小vruntime减去适当偏移),避免长期休眠的进程立即占满 CPU,同时防止饥饿。
-
一句话总结:CFS 用 vruntime 作为尺度,让每个进程按其权重获得成比例的 CPU 时间,从而实现“完全公平”。
三、nice 值每降低 1,权重有何变化?
nice 值降低 1 意味着优先级提高,对应权重增加约 25%(乘以 1.25)。
以内核预定义的权重表为例:
-
nice = 0 → 权重 1024
-
nice = -1 → 权重 1277 (1024 × 1.247 ≈ 1.25 倍)
-
nice = -2 → 权重 1586 (1277 × 1.242)
由于 vruntime 增长与权重成反比,权重变大的进程“消耗时间”更慢,最终能分配到更多的 CPU 份额。
四、使用 renice 修改运行中进程的 nice 值
renice -n 10 -p 1234
将 PID 为 1234 的进程 nice 值设为 -5
renice -n -5 -p 1234
-
普通用户只能增加自己进程的 nice 值(降低优先级,nice 值变大)。
-
root 可以任意调整(包括降低 nice 值以提高优先级)。
也可以通过 -u 按用户修改,或 -g 按进程组修改。修改后可用 top 或 ps -l 验证 NI 或 PR 列的变化。
9. 进程与内存监控命令 (top, free, pmap):在 top 命令的交互界面中,按键 1、2、3 分别有什么作用?free 输出中的 buffer 和 cache 有何区别?如何安全地清空系统缓存?如何使用 pmap 查看指定进程的内存占用与映射关系?
1. top 中按键 1、2、3 分别有什么作用?
1:显示或隐藏各 CPU 核心的使用情况,是排查单核 CPU 瓶颈最常用的快捷键。2:高亮 CPU 汇总区域,增强 CPU 使用率显示效果(不同版本表现略有差异)。3:切换 CPU 使用率显示样式(不同top版本支持情况略有不同)。
2. free 中的 buffer 和 cache 有什么区别?
- Buffer:缓存块设备和文件系统元数据(如 inode、目录项等)。
- Cache(Page Cache):缓存文件内容,加快文件读写速度。
二者都属于可回收缓存,当应用程序需要内存时,Linux 会自动释放,因此不能简单把它们视为“已占满内存”。
安全地清空系统缓存:通过向 /proc/sys/vm/drop_caches 写入不同的值即可手动释放缓存(数据不会丢失,因为缓存内容是磁盘的副本):
sync; echo 1 > /proc/sys/vm/drop_caches # 释放 page cache
sync; echo 2 > /proc/sys/vm/drop_caches # 释放可回收的 slab 对象(dentries/inodes)
sync; echo 3 > /proc/sys/vm/drop_caches # 同时释放两者
3)如何使用 pmap 查看指定进程的内存占用与映射关系?
基本用法
pmap <pid>
例如:pmap 1234
会输出该进程的虚拟内存映射情况,包括:
- 每段映射的起始地址
- 映射到什么文件/匿名区
- 每段大小
更详细查看:
pmap -x <PID>:显示扩展信息,如 RSS(实际驻留内存)、Dirty(脏页)、Swap 使用量。
pmap -d <PID>:显示偏移量和设备主次号。
pmap -q <PID>:精简输出,仅显示关键映射。
这个最常用,可以看到:
-
Kbytes:虚拟内存大小 -
RSS:实际驻留内存 -
Dirty:脏页 <b0></b0>:脏页 -
Mode:权限,如r-x,rw-<b0></b0>:权限,如 <b1></b1>, <b2></b2> -
Mapping:映射对象,如可执行文件、so、匿名内存等 -
Address:虚拟地址起始范围
10. 定时任务管理及排查:at 与 crontab 在任务调度上有何区别?系统级 crontab 与用户级 crontab 在配置格式上有何关键区别?若定时任务未能如期执行,运维人员应从哪些方面进行故障定位?请写出一条 crontab 规则:在每周一到周五凌晨 2:30 执行备份脚本 /opt/backup.sh 并且丢弃所有邮件通知。
| 对比项 | at |
crontab |
|---|---|---|
| 执行次数 | 一次性任务 | 周期性任务 |
| 执行时间 | 指定某个时间执行一次 | 按固定时间循环执行 |
| 是否长期保存 | 执行后自动删除 | 一直存在,直到手动删除 |
| 使用场景 | 临时任务、一次性维护、定时关机 | 数据备份、日志清理、监控脚本等周期性任务 |
2. 系统级 crontab 与用户级 crontab 的配置格式区别
-
用户级 crontab(通过
crontab -e编辑)
格式:分 时 日 月 周 命令
不需要指定执行用户,任务默认以该 crontab 的所有者身份运行。 -
系统级 crontab(
/etc/crontab、/etc/cron.d/中的文件)
格式:分 时 日 月 周 用户名 命令
在时间字段之后、命令之前,多一个“用户名”字段,用来指定以哪个用户的身份执行任务。 -
项目 用户级 crontab 系统级 crontab 编辑方式 crontab -e编辑 /etc/crontab或/etc/cron.d/*是否需要写用户名 否 是 配置格式 时间 + 命令时间 + 用户 + 命令执行身份 当前用户 指定用户
3)定时任务未能如期执行,如何排查?
可以从以下几个方向定位:
1. crond 服务是否正常
先看定时任务服务是否启动:systemctl status cron
必要时重启:sudo systemctl start crond
sudo systemctl enable crond
2. crontab 语法是否正确: crontab -l
检查时间字段、命令路径、是否有多余空格、特殊字符等。
建议先手工验证命令是否可执行:
3. 脚本是否有执行权限 :ls -l /opt/backup.sh; chmod +x /opt/backup.sh
并确认脚本第一行 shebang 正确,例如:#!/bin/bash
4. 环境变量问题
cron 环境非常简化,可能没有你在登录 shell 中的 PATH、JAVA_HOME 等变量。The cron environment is highly simplified and may lack variables such as PATH or JAVA_HOME that you have in your login shell.
建议:
- 脚本中使用绝对路径
- 必要时在 crontab 里显式定义环境变量
例如:PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
5. 用户权限是否允许
- 任务是以哪个用户执行的
- 该用户是否有权限访问脚本、目录、备份源、目标路径
检查:
/etc/cron.allow <b0></b0>/etc/cron.deny <b0></b0>
6. 系统日志
查看 cron 执行记录和报错信息。
常见位置:
/var/log/cron <b0></b0>/var/log/syslog <b0></b0>journalctl -u crond <b0></b0>
例如:grep CRON /var/log/cron
journalctl -u crond
7. 输出是否被邮件或重定向吞掉
cron 默认会把标准输出/错误输出通过邮件发送给用户。如果邮件服务没配,可能“看起来没执行”,但其实执行失败了。建议在任务中显式重定向日志:
/opt/backup.sh >> /var/log/backup.log 2>&1
4)crontab 规则:每周一到周五凌晨 2:30 执行 /opt/backup.sh,并丢弃所有邮件通知
30 2 * * 1-5 /opt/backup.sh >/dev/null 2>&1
-
时间字段:
30 2 * * 1-5(分 30,时 2,每周一至周五) -
丢弃输出:
> /dev/null 2>&1防止 cron 将输出通过邮件发送给用户
1. 网络分层模型对比(OSI vs TCP/IP):对比说明 OSI 七层模型与 TCP/IP 四层模型的分层结构。这两种模型在理论研究与生产实践中分别扮演了怎样的角色?
| OSI层次 | 名称 | 主要功能 | 常见协议/设备 |
|---|---|---|---|
| 第7层 | 应用层(Application) | 为应用程序提供网络服务 | HTTP、HTTPS、FTP、SMTP、DNS、SSH、Telnet |
| 第6层 | 表示层(Presentation) | 数据格式转换、加密、压缩 | SSL/TLS、JPEG、ASCII、UTF-8 |
| 第5层 | 会话层(Session) | 建立、维护、终止会话 | NetBIOS、RPC |
| 第4层 | 传输层(Transport) | 端到端通信、可靠传输、流量控制 | TCP、UDP |
| 第3层 | 网络层(Network) | 路由选择、IP寻址 | IP、ICMP、OSPF、BGP、路由器 |
| 第2层 | 数据链路层(Data Link) | MAC地址、成帧、差错检测 | Ethernet、ARP、PPP、交换机 |
| 第1层 | 物理层(Physical) | 比特流传输 | 网线、光纤、Hub、中继器 |
| TCP/IP层次 | 对应OSI层 | 主要协议 |
|---|---|---|
| 应用层 | OSI 第5~7层 | HTTP、HTTPS、FTP、DNS、SMTP、SSH、Telnet |
| 传输层 | OSI 第4层 | TCP、UDP |
| 网络层(Internet) | OSI 第3层 | IP、ICMP、ARP(教材中有时将 ARP 单独说明)、OSPF、BGP |
| 网络接口层(Link) | OSI 第1、2层 | Ethernet、PPP、Wi-Fi |
| 维度 | OSI 七层模型 | TCP/IP 四层模型 |
|---|---|---|
| 理论价值 | 网络通信的通用理论框架,概念清晰、分层严格,是学习网络原理的标准教学模型,适合描述各种网络系统。 | 因特网实际实现的现实描述,模型偏重协议本身,层次划分不如 OSI 严格,但在教学中与 OSI 对照使用。 |
| 生产实践 | 未获得市场成功:协议栈复杂、实现臃肿,几乎没有商业化产品使用完整的 OSI 协议栈。 | 全球互联网的绝对主导标准:所有 TCP/IP 网络设备、操作系统均基于此模型和协议栈构建。 |
| 分工与影响 | 作为协议设计的参考标杆:后续网络技术(如 MPLS, ATM)在功能划分上仍参照其思想;也是网络工程师认证的基础理论。 | 事实上的行业唯一标准:开发者直接面向 TCP/UDP socket 编程,运维配置路由、防火墙、负载均衡均基于 IP、端口等概念。 |
总结:
OSI 模型是“理想化的教学模型和设计蓝图”,为理解网络分层提供了完美架构;TCP/IP 模型是“现实世界的工程产物和工业标准”,驱动了整个互联网的运行。两者并非替代关系,而是理论与实践的互补。在实际工作中,我们通常以 TCP/IP 协议栈为核心,借助 OSI 的分层思想进行故障隔离和协议分析。
2. 数据的封装与解封装过程:请详细阐述数据在发送端的“封装”过程和在接收端的“解封装”过程。在解封装时,数据链路层和网络层是如何根据头部信息判断数据处理方式的?
数据在网络中传输时,并不是直接发送应用程序的数据,而是经过各层逐层添加协议头(Header)进行封装(Encapsulation);到达接收端后,再逐层去掉协议头(Decapsulation),最终还原给应用程序。
封装是指发送端数据从应用层向下传递时,每经过一层,都添加该层对应的协议头(有些层还会添加尾部),最终形成可以在网络上传输的数据。
1.以 TCP/IP 五层模型(便于描述)为例,从应用层到物理层:
-
应用层
用户数据(如 HTTP 请求报文)被生成,作为原始数据载荷传递给传输层。 -
传输层
收到应用数据后,封装 TCP 头部(或 UDP 头部),头部中包含源端口、目的端口、序列号等。此时的数据单元称为 TCP 段(Segment)。 -
网络层
收到 TCP 段后,封装 IP 头部,包含源 IP 地址、目的 IP 地址、协议号(如 TCP 为 6)等,形成 IP 数据包(Packet)。 -
数据链路层
收到 IP 数据包后,封装帧头(MAC 地址)和帧尾(FCS 校验)。帧头包括源 MAC、目的 MAC、类型字段(如 0x0800 表示上层是 IPv4)。形成 数据帧(Frame)。 -
物理层
将数据帧转换为比特流,通过物理介质(光纤、双绞线)发送出去。
封装过程可理解为每层都在数据前面加上自己的“信封”,链路层还加上了“封底”。
2.接收端的解封装过程(自下而上剥离头部)
接收端从物理层到应用层反向操作:
-
物理层
接收比特流,同步时钟,还原为数据帧后交给数据链路层。 -
数据链路层
去掉帧头和帧尾,进行 CRC/FCS 校验,根据帧类型字段将内层数据(IP 数据包)上送网络层。
——这是第一次关键判断(详见第三部分)。 -
网络层
去掉 IP 头部,检查首部校验和,根据协议字段将 TCP 段(或 UDP 数据报)上送传输层。
——这是第二次关键判断。如有分片则先重组再上交。 -
传输层
去掉 TCP/UDP 头部,根据目的端口定位到对应的 Socket(应用进程),将净荷数据提交给应用层。可能需按序列号重组、发送确认。 -
应用层
应用程序解析最终数据(如 HTTP 响应),完成通信。
-
三、解封装时数据链路层和网络层的判断机制
-
1. 数据链路层:根据目的 MAC 地址和类型字段决定“收不收、交给谁”
-
目的 MAC 地址判断接收与否
网卡收到帧后,比对帧头中的目的 MAC 地址:
-
单播:若与自身接口 MAC 完全匹配,则接收;否则丢弃(非混杂模式)。
-
广播(FF-FF-FF-FF-FF-FF):必须接收。
-
组播:若接口已加入该组播组,则接收;否则丢弃。
-
不符合上述条件的帧直接丢弃,不产生任何通知。
-
-
帧尾 FCS 校验
对整帧进行 CRC 计算,如果与帧尾的校验值不符,说明传输出错,直接丢弃该帧。
-
帧类型字段(EtherType)分用
接收有效的帧后,根据帧头中的“类型”字段决定将载荷交给哪个上层协议:
-
0x0800→ 交给 IPv4 模块 -
0x86DD→ 交给 IPv6 模块 -
0x0806→ 交给 ARP 模块 -
0x8100→ 表示 VLAN 标签,继续解析内层类型
-
-
目的 IP 地址决定数据的去向
收到 IP 数据包后,检查目的 IP 地址:-
地址属于本机(任一分接口 IP、127.0.0.1、广播地址、组播地址且本机已加入):接收数据包,进入下一步。
-
地址不属于本机,且主机开启了路由转发功能(如 Linux 的
net.ipv4.ip_forward=1):根据路由表转发,同时 TTL 减 1,若 TTL 变为 0 则丢弃并回复 ICMP 超时。 -
地址不属于本机,且未开启转发:丢弃数据包(可选择性向源发送 ICMP 不可达消息)。
-
-
首部校验和验证
IP 层校验头部是否损坏,若校验失败,直接丢弃,不产生任何错误报告。 -
分片重组
若数据包是分片,需等待所有分片到达,根据标识符重组完整 IP 数据包后才会上交。 -
协议字段(Protocol)分用
对于目的为本机的数据包,根据 IP 头中的协议号将载荷交到正确的上层:-
6→ 交给 TCP -
17→ 交给 UDP -
1→ 交给 ICMP -
89→ 交给 OSPF
-
3. 网络通信模式与双工机制:在网络通信模式中,单播(Unicast)、广播(Broadcast)和组播(Multicast)的定义与特点是什么?单工、半双工、全双工通信机制有何异同?
一、单播、广播、组播的定义与特点
| 通信模式 | 定义 | 特点 |
|---|---|---|
| 单播 (Unicast) | 源主机向单一特定目标主机发送数据,目的地址为单播 IP 或单播 MAC。 | • 一对一通信 • 需要知道接收方的确切地址 • 不浪费其他主机资源 • 典型应用:HTTP、SSH、FTP |
| 广播 (Broadcast) | 源主机向网段内所有主机发送数据,目的地址为广播地址(如 255.255.255.255 或子网广播地址)。 | • 一对所有通信 • 所有主机都必须处理广播帧,可能造成广播风暴 • 受限于广播域(通常为同一个 VLAN 或子网) • 典型应用:ARP 请求、DHCP 发现 |
| 组播 (Multicast) | 源主机向一个组播组地址发送数据,只有事先加入该组的成员才会接收。 | • 一对多通信,但仅限组成员 • 节省带宽(数据在网络中复制,不产生冗余) • 跨越路由器需要 IGMP/PIM 等协议支持 • IPv4 组播地址范围 224.0.0.0 ~ 239.255.255.255 • 典型应用:视频直播、IPTV、视频会议 |
二、单工、半双工、全双工通信机制的异同
| 双工方式 | 数据传输方向 | 同时收发 | 类比 | 典型应用 |
|---|---|---|---|---|
| 单工 (Simplex) | 只能沿单一固定方向传输,一方固定发送、另一方固定接收。 | 否 | 广播电台、电视 | 卫星广播、寻呼系统 |
| 半双工 (Half-Duplex) | 数据可以双向传输,但同一时刻只能一个方向,双方轮流发送。 | 否 | 对讲机 | 集线器 (Hub)、传统无线电 |
| 全双工 (Full-Duplex) | 数据可以同时双向传输,双方可同时发送和接收。 | 是 | 电话 | 现代交换机 (Switch)、光纤通信 |
异同总结:
-
三者的区别在于数据流的方向性与同时性:单工是“单行道”,半双工是“分时双向”,全双工是“同时双向”。
-
半双工需要冲突检测机制(如 CSMA/CD),效率较低;全双工完全消除冲突,带宽利用率最高。
-
在实际网络中,双工模式通常指物理层/链路层的通道特性,而单播/广播/组播是网络层及以上的通信目标模式,两者属于不同维度但共同决定通信效率。
4. 网卡状态查看与速率修改(mii-tool 与 ethtool):mii-tool 和 ethtool 都是网卡管理工具,它们在支持的速率范围和使用限制上有何不同?请写出查看指定网卡(如 ens160)物理链路状态的 ethtool 命令。如何使用 ethtool 强制修改网卡的速率为 1000Mbps、全双工且关闭自动协商?
一、mii-tool 与 ethtool 的差异
| 特性 | mii-tool | ethtool |
|---|---|---|
| 支持的速率范围 | 仅支持 10Mbps / 100Mbps(基于 MII 标准),不支持千兆及以上 | 支持 10M/100M/1000M(1G)/10G 甚至更高,涵盖现代高速网卡 |
| 使用限制 | 基于传统 MII 接口,仅适用于集成 MII 收发器的老旧网卡;很多新驱动已不再支持 | 广泛兼容现代网卡驱动,提供 N-way 协商、链路状态、驱动信息、EEPROM 等丰富功能,是目前标准工具 |
| 状态 | 已被淘汰,多数发行版需额外安装 net-tools 包 | 主流工具,预装于绝大多数 Linux 系统 |
二、查看指定网卡物理链路状态的 ethtool 命令
ethtool ens160
示例输出:Settings for ens160:
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
| 字段 | 含义 |
|---|---|
| Speed | 当前链路速率 |
| Duplex | 双工模式(Full/Half) |
| Auto-negotiation | 是否开启自动协商 |
| Link detected | 是否检测到物理链路(yes 表示网线已连接) |
三、强制修改网卡速率为 1000Mbps、全双工并关闭自动协商
sudo ethtool -s ens160 speed 1000 duplex full autoneg off
sudo ethtool -s <网卡名> speed <速率> duplex <模式> autoneg <on|off>
| 参数 | 含义 |
|---|---|
-s |
设置网卡参数 |
speed |
链路速率(如 10、100、1000、10000) |
duplex |
full(全双工)或 half(半双工) |
autoneg |
是否开启自动协商(on / off) |
5. 组网设备(集线器、交换机、路由器):集线器(Hub)、交换机(Switch)和路由器(Router)分别工作在 OSI 模型的哪一层?当交换机收到一个数据帧时,若在 MAC 地址表中找不到目的 MAC 地址,它会做出怎样的处理?交换机和路由器在隔离冲突域和广播域上有何不同?
1、工作层级
-
集线器(Hub):工作在 OSI 第 1 层(物理层)。它仅对电信号进行复制、放大和转发,不理解帧结构。
-
交换机(Switch):工作在 OSI 第 2 层(数据链路层)。它根据 MAC 地址表进行帧转发,能识别帧头和 MAC 地址。
-
路由器(Router):工作在 OSI 第 3 层(网络层)。它根据 IP 地址和路由表进行数据包转发,连接不同网络。
2、交换机对未知目的 MAC 地址的处理:泛洪
当交换机收到一个数据帧,且帧中的目的 MAC 地址不在 MAC 地址表中(即“未知单播”),交换机会执行泛洪操作:
-
把该帧从除接收端口以外的所有同 VLAN 端口转发出去。
-
这种处理保证了即使交换机还没学习到目的设备的位置,帧也能到达目标(如果存在)。
-
同时,交换机学习到源 MAC 和端口的对应关系,更新 MAC 地址表。
3、交换机和路由器在隔离冲突域、广播域上的区别
| 设备 | 冲突域 | 广播域 |
|---|---|---|
| Hub | 不隔离(所有端口一个冲突域) | 不隔离(一个广播域) |
| Switch | 隔离冲突域(每个端口一个冲突域) | 不隔离广播域(默认整个交换机属于同一广播域,未划分 VLAN 时) |
| Router | 隔离冲突域 | 隔离广播域 |
-
交换机通过微分割消除了冲突,但泛洪未知帧、广播帧和组播帧,因此广播域仍是整个交换网络。
-
路由器是广播域的边界,除非特别配置(如 DHCP 中继),否则广播包不会被路由到其他网络,这能有效控制广播风暴范围。
6. 虚拟机网络连接模式:在虚拟机(VMware)的网络配置中,桥接模式、NAT 模式和仅主机模式(Host-Only)的特点是什么?虚拟机分别是通过宿主机的哪些虚拟设备(如 Vmnet0/1/8)进行连接的?
| 连接模式 | 特点 | 虚拟机能否访问外网 | 宿主机与虚拟机通信 | 外部网络能否直接访问虚拟机 |
|---|---|---|---|---|
| 桥接模式 (Bridged) | 虚拟机像一台独立主机直接连接到物理交换机,与宿主机同等地位,获取同一网段的 IP 地址。完全融入物理网络,可提供网络服务。 | 能,通过物理网关直接访问 | 同一网段,直接通信 | 能,其他主机可直接访问虚拟机 IP |
| NAT 模式 (Network Address Translation) | 虚拟机通过宿主机提供的 NAT 服务访问外部网络,外部网络只看到宿主机的 IP。虚拟机使用私有 IP(默认 192.168.xx.0/24),由 VMware 的 DHCP 分配。宿主机充当虚拟机的网关和 DNS。 | 能,通过宿主机 NAT 转换 | 宿主机与虚拟机共享私有网段,可直接通信(宿主机有对应虚拟网卡 IP) | 不能,需要端口转发等特殊配置 |
| 仅主机模式 (Host-Only) | 虚拟机与宿主机组成一个完全隔离的私有网络,不能访问外部网络(除非宿主机关联其他网络或启用路由)。虚拟机使用私有 IP,由 VMware 的 DHCP 分配。适合搭建测试环境、安全隔离。 | 不能,除非宿主机做特殊转发 | 可以,通过私有虚拟网络直接通信 | 不能,与外部网络隔离 |
对应的 VMware 虚拟网络设备
| 连接模式 | 默认虚拟交换机 | 宿主机上的虚拟网卡 | 说明 |
|---|---|---|---|
| 桥接模式 | VMnet0 | 不单独显示虚拟网卡;桥接到宿主机物理网卡 | VMnet0 是虚拟桥接设备,将虚拟机的网络数据直接送到物理交换机,宿主机通常不显示名为 VMnet0 的适配器 |
| NAT 模式 | VMnet8 | VMware Network Adapter VMnet8 | 宿主机上会添加一个 IP 地址为 192.168.x.1 的虚拟网卡(x 为子网号,通常是 192.168.8.1),用于与虚拟机通信;VMnet8 交换机连接 NAT 服务与 DHCP 服务 |
| 仅主机模式 | VMnet1 | VMware Network Adapter VMnet1 | 宿主机上会添加一个 IP 地址为 192.168.y.1 的虚拟网卡(y 为子网号,通常 192.168.1.1),用于与虚拟机通信;VMnet1 交换机提供 DHCP,但无 NAT 功能 |
7. 网卡名规范与命名规则修改:从 CentOS 7/Rocky 开始,系统默认采用可预测网络接口命名规则。在批量部署时,如何通过修改内核引导参数将其恢复为传统的 eth0 格式?在 CentOS 9/Rocky 9 及以后版本中,网卡配置文件存放在哪个路径下?(传统的 CentOS 7 与现代 Rocky 9 的路径有何不同?)
一、通过内核引导参数恢复传统 eth0 命名
在 CentOS 7/Rocky 及之后版本,默认使用 可预测网络接口命名(如 enp0s3、ens33),批量部署时如需回归传统的 eth0、eth1 命名,可修改内核引导参数:
-
编辑
/etc/default/grub
在GRUB_CMDLINE_LINUX行末尾追加两个参数:GRUB_CMDLINE_LINUX="... net.ifnames=0 biosdevname=0"
net.ifnames=0:禁止 systemd 的可预测命名策略,回退到内核传统的ethX命名。biosdevname=0:禁用 Dell 的 biosdevname 命名插件(部分机型可能会产生emX或pXpX),确保彻底回退。 -
重新生成 GRUB 配置
-
BIOS 引导:
grub2-mkconfig -o /boot/grub2/grub.cfg -
UEFI 引导:
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg(路径视发行版而定)
-
-
重启系统
重启后网卡名称将变为eth0、eth1等传统格式。
| 系统版本 | 默认配置路径 | 文件名格式 | 说明 |
|---|---|---|---|
| CentOS 7 | /etc/sysconfig/network-scripts/ |
ifcfg-<名称> (如 ifcfg-eth0) |
传统 network-scripts 服务管理,依赖 network 服务 |
| CentOS 9 / Rocky 9 | /etc/NetworkManager/system-connections/ |
<连接名>.nmconnection (如 eth0.nmconnection) |
默认使用 NetworkManager 的 keyfile 格式;也可兼容旧格式,但需安装 network-scripts 包并将文件放回原路径 |
从 CentOS 8 / Rocky 8 开始,网络配置主管理工具变为 NetworkManager,默认生成 .nmconnection 文件,不再使用 /etc/sysconfig/network-scripts/ 下的 ifcfg 文件(除非手动安装 network-scripts 包并切换)。
在 Rocky 9 中,推荐直接使用 nmcli 或 nmtui 管理配置,文件自动存放于上述路径。
批量部署时,可按新规范提供
.nmconnection文件,或在内核参数回退命名的同时,将传统ifcfg文件放回旧路径并确保NetworkManager兼容读取。
8. IP 子网划分实践:某公司获得了 10.240.0.0/13 的网段,现在需要为其市内 16 个区划分子网。请计算出:
1) 每个区子网的子网掩码(Netmask,用点分十进制表示)。
2) 每个子网可容纳的可用主机数。
3) 各个子网中,最小的网段(Network ID)和最大的网段(Network ID)。
每个区子网的子网掩码(点分十进制)
原有 /13 网络,现需划分 16(2⁴)个子网,需从主机位借用 4 位作为子网位,因此新掩码为 /17,点分十进制表示为:
255.255.128.0
每个子网可容纳的可用主机数
子网掩码 /17,剩余主机位 32 - 17 = 15 位。
可用主机数 = 2¹⁵ - 2 = 32768 - 2 = 32766(减去网络地址和广播地址)。
最小网段与最大网段
原网络 10.240.0.0/13 中,第二个八位组范围固定为 240~247(前 5 位网络位为 11110),后 3 位 + 第三、四八位组为可划分位。
借用 4 位子网位(第二个八位组后 3 位 + 第三个八位组首位),可形成 16 个子网。
-
最小网段(第一个子网):子网位全 0
10.240.0.0/17 -
最大网段(最后一个子网):子网位全 1
第二个八位组后 3 位 111 → 247,第三个八位组首位 1 → 128
10.247.128.0/17
所有子网 ID 依次为:10.240.0.0/17, 10.240.128.0/17, 10.241.0.0/17, 10.241.128.0/17, ……, 10.247.0.0/17, 10.247.128.0/17。
9. 超网合并与路由聚合:什么是超网(合并超网)?它与子网划分有什么区别?请写出将 220.78.168.0/24 到 220.78.175.0/24 这 8 个连续的小网段合并为一个超网的计算过程和最终合并网段。
1、什么是超网?与子网划分的区别
-
超网(Supernetting,又称路由聚合)
将多个连续的小网络合并成一个更大的网络,通过缩短子网掩码(即减少网络前缀长度)来实现。超网主要用于路由聚合,可大幅缩减路由表条目、优化路由效率。 -
子网划分(Subnetting)
将一个大的网络分割成多个较小的子网,通过延长子网掩码(即增加网络前缀长度)来实现,目的是更精细地管理 IP 地址、控制广播域。 -
对比项 子网划分(Subnet) 超网合并(Supernet) 本质 一个大网拆成多个小网 多个小网合并成一个大网 前缀变化 前缀变长(借主机位) 前缀变短(减少网络位) 网络数量 增加 减少 每网主机数 减少 增加 应用场景 企业内部分配 IP 路由汇总、减少路由表
将 220.78.168.0/24 ~ 220.78.175.0/24 合并为一个超网
计算过程:
-
确认连续性与范围
共 8 个连续的 C 类网段,第三个八位组从 168 到 175(即 2³=8 个网络块)。 -
写出关键八位组的二进制
前两个八位组固定为220.78,第三个八位组:十进制 二进制 168 10101000 169 10101001 170 10101010 171 10101011 172 10101100 173 10101101 174 10101110 175 10101111 -
确定共同的网络前缀
这 8 个地址的前 5 位同为10101,后 3 位变化从000到111。
因此第三个八位组中,前 5 位仍属于网络部分,后 3 位划入主机部分。 -
计算新的子网掩码
原有 /24(前 3 个八位组全为网络位),现向后退 3 位(因为合并了 2³=8 个网段,借用 3 位主机位)。
新前缀长度 = 24 - 3 = 21,即/21。
点分十进制掩码:255.255.248.0(第三个八位组 248 = 11111000)。 -
确定超网网络地址
网络地址为主机位全 0,即第三个八位组后 3 位为 0 的最小地址:
220.78.168.0 (168 = 10101000)
最终合并网段:
220.78.168.0/21 (子网掩码 255.255.248.0)
该超网包含 220.78.168.0 ~ 220.78.175.255 的所有地址,涵盖 8 个 /24 子网的完整地址范围。
1. Linux 系统启动流程阶段:详细描述 Linux 系统从通电自检到登录界面的五个主要启动阶段。
1. Linux 系统启动流程阶段
Linux 系统从按下电源键到出现登录界面,一般可以分为 五个主要启动阶段:
-
BIOS/UEFI(加电自检)
-
Boot Loader(GRUB2 引导程序)
-
Kernel(Linux 内核)
-
initramfs + systemd(PID 1 初始化)
-
启动系统服务并进入登录界面
第一阶段:BIOS/UEFI 固件与硬件自检 (POST)
-
基本任务
系统主板上的固件(传统 BIOS 或现代 UEFI)开始执行,首先进行上电自检(POST, Power-On Self Test),检测 CPU、内存、磁盘控制器、键盘等关键硬件是否正常。 -
初始化与设备枚举
固件初始化硬件设备,为它们分配中断、I/O 端口等资源。UEFI 还会加载更丰富的驱动并支持图形界面。 -
定位可启动设备
根据固件设置中的启动顺序(Boot Order),依次扫描硬盘、SSD、USB、网络等设备,寻找第一个包含有效引导代码的设备。 -
加载引导程序
对 MBR 分区的传统 BIOS 系统,固件读取硬盘的主引导记录(MBR),并执行其中的第一段引导代码;对 GPT + UEFI 系统,固件直接访问 EFI 系统分区(ESP),查找并执行.efi格式的引导管理器。
第二阶段:引导加载程序 (Boot Loader)
目前大多数 Linux 发行版使用 GRUB2(GRand Unified Bootloader 2),其工作分两(或三)个步骤:
-
阶段 1/阶段 1.5
-
BIOS 模式下,MBR 中的
boot.img被加载,由于其容量极小,它的作用是定位并加载位于磁盘固定区域的core.img。core.img包含文件系统模块,能访问/boot分区。 -
UEFI 模式下,固件直接加载
grubx64.efi,无需 MBR 跳转。
-
-
阶段 2:加载 GRUB 配置与内核选择
-
core.img读取/boot/grub2/grub.cfg(或/boot/grub/grub.cfg),展示启动菜单。用户可选择内核版本、恢复模式,或修改启动参数。 -
最后,GRUB 将指定的 Linux 内核映像(vmlinuz) 和 初始 RAM 磁盘(initramfs / initrd) 加载到内存中。
-
-
控制权转移
GRUB 设置好内核参数(如root=、ro、quiet、splash、net.ifnames=0等),然后跳转到内核入口点,由内核接管系统。
第三阶段:内核初始化
-
内核自解压
内核映像常是经过压缩的(如 bzImage),它会先解压到内存高地址区,然后执行真实的内核启动代码。 -
硬件再初始化与子系统初始化
内核不依赖于固件的初始化结果,会重新探测并初始化所有硬件:CPU 特性、内存管理单元、中断控制器、定时器、各种总线(PCIe、USB)等。同时初始化内核子系统(进程调度器、内存管理、VFS、网络协议栈)。 -
加载 initramfs 与挂载临时根文件系统
内核将 initramfs 中的微型根文件系统解压到内存作为临时根(/),并运行其中的/init脚本。initramfs 包含设备驱动(如 SCSI、LVM、RAID)、文件系统模块、网络、磁盘加密工具等,用于完成磁盘发现、解密、挂载真正的根文件系统。 -
切换根文件系统并启动第一个用户进程
/init脚本完成必要的准备工作后,执行pivot_root或switch_root操作,卸载 initramfs 临时根,挂载实际根文件系统。最后,内核启动第一个用户态进程:/sbin/init(或 systemd 符号链接的目标),其 PID 为 1。
第四阶段:init 进程初始化(以 systemd 为例)
现代发行版普遍使用 systemd 作为 PID 1 的初始化系统,取代传统的 SysV init。
-
进入默认目标 (default.target)
systemd 首先解析其主配置文件/etc/systemd/system.conf和/etc/systemd/system/default.target,确定系统的启动级别(如multi-user.target文本模式,或graphical.target图形模式)。 -
并行激活系统服务
systemd 根据单元(unit)的依赖关系和顺序,大量并行启动基础服务与组件:-
挂载本地文件系统(
local-fs.target) -
激活 swap 分区
-
设置主机名
-
初始化网络(
network.target)、防火墙 -
启动 udev 设备管理器(动态管理
/dev) -
启动各种守护进程:sshd、crond、rsyslog、dbus 等
-
检查 SELinux 策略(如启用)
-
-
启动登录管理器
若目标为graphical.target,systemd 会启动显示管理器(如 GDM、LightDM、SDDM);若为multi-user.target,则启动多个虚拟控制台的getty服务(getty@tty1、getty@tty2等),等待用户登录。
第五阶段:用户登录界面
-
文本控制台登录
对于多用户文本模式,getty进程在 tty 终端上输出login:提示符,等待用户输入用户名。用户按下回车后,getty调用login程序验证密码。认证通过后,login启动用户的默认 shell(如/bin/bash),并执行/etc/profile、~/.bash_profile等配置文件,呈现命令行环境。 -
图形界面登录
显示管理器(如 GDM)在显示器上绘制图形登录界面,用户在字段中输入凭证。显示管理器通过 PAM(可插拔认证模块)进行身份验证,成功后启动 Xorg/Wayland 会话以及桌面环境(GNOME、KDE 等),最终呈现可交互的桌面。
此时,整个 Linux 系统的启动流程结束,系统进入就绪状态,等待用户操作。
2. BIOS 与 UEFI 启动模式对比:从磁盘分区支持、启动速度、启动逻辑和安全性四个维度对比传统的 BIOS 引导模式和现代的 UEFI 引导模式的差异。
1.磁盘分区支持
| 对比维度 | BIOS(传统) | UEFI(现代) |
|---|---|---|
| 磁盘分区支持 | MBR(最大约 2TB,最多 4 个主分区) | GPT(支持超大容量磁盘,可创建大量分区) |
| 启动速度 | 较慢,逐项初始化硬件 | 较快,并行初始化硬件,启动效率更高 |
| 启动逻辑 | 从 MBR(硬盘前 512B) 加载 Boot Loader(如 GRUB) | 从 EFI System Partition(ESP) 直接加载 .efi 启动程序 |
| 安全性 | 基本无启动安全机制 | 支持 Secure Boot(安全启动),可验证启动程序签名,防止恶意 Boot Loader |
2.启动速度
| 维度 | BIOS | UEFI |
|---|---|---|
| 运行模式 | 16 位实模式,寻址能力 1MB,运行效率低 | 32 位/64 位保护模式,可直接访问全部内存,运行效率高 |
| 硬件初始化 | 按顺序串行检测与初始化所有硬件设备(如磁盘、键盘),耗时较长 | 支持 并行设备初始化,固件可同时初始化多个设备,大幅缩短 POST 时间 |
| 引导加载过程 | 经过 MBR → 活动分区引导扇区 → 引导加载程序等多级跳转,过程繁琐 | 固件直接从 EFI 系统分区加载 .efi 文件,一步到位,减少 I/O 次数,启动更快 |
| 电源管理 | 依赖 16 位 APM 标准,切换慢 | 原生支持 ACPI,可更快完成电源状态切换 |
3. 启动逻辑
| 维度 | BIOS | UEFI |
|---|---|---|
| 引导方式 | 固件读取第一个启动磁盘的 MBR 前 446 字节(引导代码),由该代码再加载活动分区的引导扇区(如 GRUB stage1),进而载入第二阶段的引导程序 | 固件读取 EFI 系统分区(ESP)(FAT32 文件系统)中的引导文件,如 \EFI\BOOT\BOOTx64.efi,或按 NVRAM 记录的启动项路径加载 |
| 引导代码限制 | MBR 中的引导代码仅 446 字节,功能极弱,难以承载文件系统驱动,通常必须借助后续阶段(如 stage1.5)才能访问 /boot |
.efi 文件大小无严格限制(仅受 ESP 分区容量约束),可直接包含完整的文件系统驱动、图形界面等,功能强大 |
| 多系统支持 | 需要将控制权交给多个引导管理器(如链式加载),容易互相覆盖,管理复杂 | 原生支持 多启动项并存,每个操作系统可在 ESP 有自己的目录,互不干扰,通过 UEFI 启动菜单轻松切换 |
| 启动参数传递 | 通过内核命令行参数直接传递给内核,或通过 setup sector 等遗留结构 | 通过 UEFI 变量、设备路径协议等标准化方式传递,更规范 |
4. 安全性
| 维度 | BIOS | UEFI |
|---|---|---|
| 固件级安全 | 无内置安全验证机制,传统 BIOS 不校验引导代码的合法性,极易被 Bootkit 或恶意 MBR 篡改 | 支持 Secure Boot(安全启动):固件在加载 .efi 文件时验证其签名,只有被信任的密钥签名的引导程序/内核才允许执行,有效防止未授权代码在启动阶段运行 |
| 信任链建立 | 无法建立从固件到操作系统的完整信任链 | 可与 TPM(可信平台模块) 配合,实现 测量启动(Measured Boot),将启动各阶段的哈希值记录到 PCR,用于远程证明 |
| 运行时保护 | 通常无运行时服务,启动后固件不再参与系统管理 | UEFI 提供运行时服务,操作系统可通过 UEFI Runtime Services 管理 NVRAM 变量(如启动顺序)、配合 UEFI 安全策略 |
| 固件更新 | 更新固件通常需要通过 DOS 工具或特定程序,流程繁琐且风险高 | 支持 UEFI Capsule Update 机制,可在操作系统中安全地更新固件,甚至由厂商推送更新 |
总结:BIOS 是陈旧的技术标准,受限于 16 位实模式和 MBR 的分区瓶颈,启动慢且不安全;UEFI 则从根本上进行了革新,以 GPT 分区、并行初始化、Secure Boot 等特性提供了大容量支持、快速启动和高安全性,已成为现代计算机的主流固件标准。
3. Bootloader 作用与类型:Bootloader(引导加载器)的核心作用是什么?除了现代 Linux 默认的 GRUB2 之外,还有哪些常见的 Linux Bootloader 类型(请写出至少 3 种)?
Bootloader(引导加载器)是操作系统启动过程中最重要的程序之一,位于 BIOS/UEFI 和 Linux Kernel 之间,负责将 Linux 内核加载到内存并将控制权交给内核,其核心作用包括:
-
定位并加载内核:从硬盘、SSD 等存储介质中找到操作系统内核映像(如
vmlinuz),将其读入内存。 -
加载 initramfs/initrd:同时将临时根文件系统镜像加载到内存,为内核提供启动所需的基础驱动和工具。
-
传递启动参数:向内核传递命令行参数(如根文件系统位置、调试标志等),指导内核如何启动。
-
提供启动菜单:在多内核或多操作系统环境下,允许用户选择要启动的系统。
-
移交控制权:完成所有准备后,跳转到内核入口点,将 CPU 控制权完全交给操作系统。
常见的 Linux Bootloader(除 GRUB2 外)
-
LILO (Linux Loader)
早期 Linux 的主流引导器,配置变更后需重新执行lilo命令写入 MBR。不支持大硬盘、多文件系统,目前已基本被淘汰,但在极小系统或嵌入式场景中仍偶尔可见。 -
SYSLINUX 系列
一套轻量级引导程序家族,适用于不同介质:-
SYSLINUX:FAT 文件系统(如 USB 启动盘)
-
ISOLINUX:ISO 9660 光盘启动
-
PXELINUX:网络 PXE 启动
-
EXTLINUX:ext2/3/4、btrfs 等文件系统
常用于安装介质、LiveCD、PXE 服务器。
-
-
systemd-boot
原名 gummiboot,是专为 UEFI 系统 设计的极简引导管理器,不包含文件系统驱动,只读取 EFI 系统分区(ESP)中的内核镜像。配置文件简单,启动极快,常用于 Arch Linux、Clear Linux 等发行版。 -
rEFInd
一个基于 EFI 的图形化引导管理器,可自动扫描 ESP 中的内核文件并生成启动菜单,支持多操作系统(Linux、Windows、macOS)。界面美观,无需复杂配置,适合 UEFI 多系统环境。 -
EFISTUB
严格来说不是独立引导程序,而是 Linux 内核自身的 EFI 可执行封装。内核可被 UEFI 固件直接加载,无需任何中间引导器,通过 UEFI Shell 或efibootmgr直接添加启动项。极致简洁,但灵活性低。 -
U-Boot (Das U-Boot)
广泛应用于 ARM、RISC-V 等嵌入式平台 的开源引导器,功能丰富,支持网络加载内核、多种文件系统和设备树,是物联网和嵌入式设备的首选。
4. 内核加载与 initramfs 工作机制:在系统引导时,vmlinuz 和 initramfs 镜像分别起什么作用?请详细描述 initramfs 临时根文件系统的工作流程,它最终是如何切换到真正的根文件系统的?
一、vmlinuz 与 initramfs 的作用
-
vmlinuz(内核映像)
压缩后的 Linux 内核可执行文件。它包含内核核心代码、进程调度、内存管理、网络协议栈等基础子系统,以及编译时内建的硬件驱动。启动时由 bootloader 加载到内存,解压后执行,完成 CPU、内存、中断等最核心的初始化。但为了保持内核的精简与通用性,它不包含所有可能的驱动(如磁盘控制器、文件系统、RAID、网络等),因此需要一个辅助的环境来加载根文件系统所需的驱动和配置,这就是 initramfs 存在的意义。 -
initramfs(初始 RAM 文件系统)
一个压缩的微型根文件系统镜像(通常为 cpio 归档格式),包含内核启动挂载真正根文件系统所必需的一切:硬件驱动模块、LVM/RAID 管理工具、文件系统格式化工具(如fsck)、磁盘加密(如 LUKS)解密工具、网络配置脚本等。它作为内核启动后的临时根目录,保证内核能够访问硬件并准备好真实的根文件系统。二、initramfs 临时根文件系统的工作流程
-
加载与展开
引导加载器将 initramfs 镜像加载到内存,与内核映像一同存放。内核启动时识别 initramfs 并将其解压到内存中的 rootfs(一个基于内存的 tmpfs),作为初始根文件系统。 -
执行 /init 脚本
内核挂载 rootfs 后,运行其中唯一的/init程序(通常是 shell 脚本或 systemd-udev 的简化版)。这个脚本是 initramfs 的操作核心。 -
硬件探测与驱动加载
/init脚本利用内核的 udev 或 mdev 等机制探测硬件,自动加载相应驱动模块,特别是磁盘控制器驱动(如 SATA、SCSI、NVMe)和文件系统驱动(如 ext4、xfs、btrfs)。 -
构建存储堆栈
如果根文件系统位于高级存储上,/init会在此阶段处理:-
mdadm 激活 RAID 阵列
-
LVM 扫描并激活逻辑卷组
-
cryptsetup 解密 LUKS 加密分区(可能会提示输入密码)
-
multipath 配置多路径
-
-
挂载真正的根文件系统
完成上述准备后,/init将真正的根文件系统挂载到临时挂载点(如/sysroot)。 -
切换根文件系统
最后,/init执行switch_root操作,完成从临时根到真实根的切换(具体过程见下节)。 -
移交控制权
切换后,临时 initramfs 所占用的内存被释放,系统在真正的根文件系统上执行/sbin/init(或 systemd),进入正常的系统初始化流程。
三、切换到真正的根文件系统的具体过程
initramfs 通过 switch_root 命令完成从内存临时根到磁盘真实根的彻底切换,步骤如下:
-
挂载关键虚拟文件系统
在切换到真实根之前,/init会确保以下虚拟文件系统已挂载到新根的相应目录,使系统环境保持完整:mount --move /proc /sysroot/proc
mount --move /sys /sysroot/sys
mount --move /dev /sysroot/dev -
执行 switch_root 系统调用
switch_root完成三个原子操作:-
将当前根文件系统(即 initramfs 的 rootfs)的挂载点从 / 移走。
-
将
/sysroot(真实根文件系统)挂载到 /。 -
清空 旧 rootfs 上的所有文件和目录,释放内存。
-
-
运行新根的 init
switch_root随后立即执行用户指定的 init 程序(通常为/sbin/init或 systemd)。此时,进程 1 的根目录已变为磁盘上的真实文件系统,initramfs 完全退出历史舞台,整个启动过程进入常规的 init 初始化阶段。
5. 运行级别(Runlevel)与 Systemd Target:传统的 SysV init 运行级别(0-6)在 systemd 中是如何对应的?在 systemd 中最核心的两个运行 target 是什么?如何使用命令查看和修改系统默认的运行级别?
1、传统 SysV init 运行级别与 systemd target 的对应关系
| SysV 运行级别 | 含义 | 对应的 systemd target |
|---|---|---|
| 0 | 关机 | poweroff.target (由 runlevel0.target 链接) |
| 1 | 单用户模式(维护) | rescue.target (由 runlevel1.target 链接) |
| 2 | 多用户模式(无 NFS 等部分网络服务) | multi-user.target (由 runlevel2.target 链接) |
| 3 | 完整多用户文本模式 | multi-user.target (由 runlevel3.target 链接) |
| 4 | 用户自定义/未使用 | 通常也指向 multi-user.target (由 runlevel4.target 链接) |
| 5 | 多用户图形模式 | graphical.target (由 runlevel5.target 链接) |
| 6 | 重启 | reboot.target (由 runlevel6.target 链接) |
| SysV Runlevel | systemd Target |
|---|---|
| 0 | poweroff.target |
| 1 | rescue.target |
| 2 | multi-user.target |
| 3 | multi-user.target |
| 4 | multi-user.target(通常) |
| 5 | graphical.target |
| 6 | reboot.target |
二、Systemd 中最核心的两个运行 target
-
multi-user.target
完整的多用户文本模式,激活所有基础系统服务(网络、守护进程、getty 等),但不启动图形显示管理器。是服务器系统的常见默认目标,相当于传统的运行级别 3。 -
graphical.target
在multi-user.target基础上再启动图形显示管理器(如 GDM、LightDM),提供桌面登录界面。是桌面系统的常见默认目标,相当于传统的运行级别 5。
查看系统默认启动目标:systemctl get-default
修改系统默认的 target:
# 设置为多用户文本模式(类似运行级别3)
systemctl set-default multi-user.target
# 设置为图形界面模式(类似运行级别5)
systemctl set-default graphical.target
6. 系统启动耗时分析:当系统启动缓慢时,我们可以使用哪些 systemd-analyze 命令来分析各个服务的启动耗时?如何将启动过程生成为图表形式的 HTML 文件?
一、分析启动耗时常用命令
| 命令 | 作用 |
|---|---|
systemd-analyze time |
显示启动总时间,拆分为内核、initramfs、用户空间三个阶段的耗时,快速判断瓶颈在哪个阶段。 |
systemd-analyze blame |
按初始化耗时从长到短列出所有服务,直接显示每个服务自身初始化所花费的时间(不含等待依赖)。 |
systemd-analyze critical-chain |
显示从启动开始到默认目标的关键时间依赖链,红色高亮最慢的环节,可指定目标如 network-online.target。 |
systemd-analyze dot |
输出 Graphviz 格式的依赖关系描述,可渲染为图片,用于分析服务启动顺序和循环依赖。 |
二、生成图表形式的 HTML 文件
systemd-analyze plot 命令可以生成启动过程的甘特图(SVG 格式),虽然它本身不直接输出 HTML,但可以通过两种方式获得可交互的 HTML 图表。
1.生成 boot.svg,然后直接用浏览器打开或嵌入到 HTML 页面中。
2.使用第三方工具或自行编写 HTML,将 SVG 嵌入页面展示。
7. 传统的 SysV init 自启动脚本配置:在传统的 SysV init(CentOS 6)中,如果使用 chkconfig 管理自建服务,自定义脚本的首部必须包含类似 # chkconfig: 2345 90 60 的配置行。请详细解释这一配置行中三个数字/数字串(2345、90、60)的具体含义,以及它们与 /etc/rc.d/ 目录下 S 和 K 软链接的关系。
在 CentOS 6 / RHEL 6 等采用 SysV init 的系统中,自定义服务如果要使用 chkconfig 管理,启动脚本(通常放在 /etc/init.d/)的开头必须包含类似下面的配置:# chkconfig: 2345 90 60
# description: My Service
# chkconfig: 2345 90 60
│ │ │
│ │ └── 停止优先级(Stop Priority)
│ └───── 启动优先级(Start Priority)
└────────── 默认运行级别(Runlevel)
三个数字的具体含义
| 数值 | 含义 |
|---|---|
| 2345 | 指定该服务在哪些运行级别自动启动。此处表示在运行级别 2、3、4、5 下,该服务会被自动启动;其他运行级别(0、1、6)下则默认不启动(或会被关闭) |
| 90 | 启动优先级(Start priority)。该数字用于生成 rcX.d 中的 S 软链接,数字越小越先启动。此处 90 意味着该服务的启动脚本会以 S90 开头,在大多数服务之后启动(常见系统服务通常在 1~50) |
| 60 | 关闭优先级(Kill priority)。该数字用于生成 rcX.d 中的 K 软链接,数字越小越先关闭。此处 60 意味着在关机或切换运行级别时,该服务会以 K60 开头被较早停止 |
通常 启动优先级 + 关闭优先级 = 100,符合“先启动的后关闭”依赖原则,但并非强制。
二、与 /etc/rc.d/ 目录下 S 和 K 软链接的关系
SysV init 的运行级别机制依赖于 /etc/rc.d/init.d/ 中的服务脚本,以及 /etc/rc.d/rcX.d/ 目录中的符号链接(X 为运行级别数字)。
-
S 链接(Start)
格式:S<两位数字><服务名>(例如S90myservice)→ 指向/etc/init.d/myservice-
系统进入对应运行级别时,
init进程会按照 数字从小到大的顺序 依次执行Sxx链接对应的脚本,并传入start参数。 -
chkconfig行中的第二个数字 90 决定了生成的 S 链接编号为S90,数字越大代表启动越晚。
-
-
K 链接(Kill)
格式:K<两位数字><服务名>(例如K60myservice)→ 同样指向/etc/init.d/myservice-
系统离开对应运行级别(或关机)时,
init进程按照 数字从小到大的顺序 依次执行Kxx链接对应的脚本,并传入stop参数。 -
chkconfig行中的第三个数字 60 决定了生成的 K 链接编号为K60,数字越小代表关闭越早。
-
当管理员执行 chkconfig --add myservice 时,chkconfig 读取脚本头部的这行配置,根据指定的运行级别自动在 /etc/rc.d/rc2.d/、rc3.d/ 等目录下创建相应的 S 和 K 软链接。
例如:
-
rc3.d/S90myservice→ 启动时执行myservice start(第 90 个启动) -
rc3.d/K60myservice→ 关闭时执行myservice stop(第 60 个关闭) -
rc0.d/K60myservice→ 关机时执行myservice stop
一句话总结:
2345决定在哪些运行级别生成 S 链接,90决定 S 链接的先后顺序(启动顺序),60决定 K 链接的先后顺序(关闭顺序),从而精确控制服务的启动和停止行为。
8. 核心启动文件损坏救援实操:如果在 Rocky 10 或 CentOS 系统中,由于误操作导致内核文件 vmlinuz 丢失或者 initramfs 镜像丢失,系统无法引导。请问:
1) 制作 initramfs 临时根镜像文件在 CentOS 6 和 Rocky 10 中分别使用什么命令?
2) 简述使用系统光盘进入救援模式(Rescue Mode)修复丢失内核或 initramfs 的核心操作步骤。
1).制作 initramfs 的命令差异
| 系统版本 | 生成 initramfs 的主要命令 |
|---|---|
| CentOS 6 | 传统命令 mkinitrd 依然可用,但底层已切换到 dracut。实际推荐使用 dracut:dracut -f /boot/initramfs-$(uname -r).img $(uname -r)或 mkinitrd /boot/initramfs-$(uname -r).img $(uname -r) |
| Rocky 10 (及所有现代 RHEL 系列) | 统一使用 dracut:dracut -f /boot/initramfs-$(uname -r).img $(uname -r)mkinitrd 此时仅为 dracut 的符号链接,实际仍调用 dracut。 |
2.使用救援模式修复的核心步骤
以下步骤以 Rocky/CentOS 安装光盘进入救援模式,修复丢失的 vmlinuz 或 initramfs 为例:
① 用安装光盘启动进入救援模式
-
从光盘/U盘引导,在启动菜单选择 “Troubleshooting” → “Rescue a Rocky Linux system”(或 CentOS 类似选项)。
-
系统询问是否挂载原有系统,选择 “1” (Continue) 以读写方式将原有根分区挂载到
/mnt/sysimage。
② 挂载必要的文件系统并 chroot
# 救援环境会自动挂载根分区,但 /boot、/dev、/proc 等可能需要手动处理
chroot /mnt/sysimage /bin/bash
mount -o remount,rw / # 确保根可写(如果挂载为只读)
mount -a # 根据 /etc/fstab 挂载所有分区(包括 /boot)
③ 根据丢失的文件类型进行修复
-
若 initramfs 丢失:直接重新生成
initramfs dracut -f /boot/initramfs-$(uname -r).img $(uname -r) # 重建当前内核的
若内核版本不确定,可查看
/lib/modules下的目录名,指定对应版本。 -
若内核文件 vmlinuz 丢失:重新安装内核包
# 对于 Rocky 10 或 CentOS 8/9 使用 dnf,CentOS 7 使用 yum dnf reinstall kernel # 或 yum reinstall kernel
如果网络不通,也可以从光盘的 Packages 目录中手动提取 kernel 包并安装:
rpm -ivh --replacepkgs /run/media/.../Packages/kernel-*.rpm
④ 重建 GRUB 引导配置
确保 /boot/grub2/grub.cfg 包含新内核或 initramfs:
grub2-mkconfig -o /boot/grub2/grub.cfg # UEFI 系统还需检查 EFI 条目
⑤ 重新安装 GRUB(若引导扇区本身也被破坏)
# BIOS 模式 grub2-install /dev/sda # UEFI 模式 grub2-install --target=x86_64-efi --efi-directory=/boot/efi
⑥ 退出 chroot 并重启
exit # 退出
chroot umount -R /mnt/sysimage # 安全卸载
reboot
重启后,系统应能正常通过丢失的文件引导。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)