面试 · 系统串联题
这份是什么? 前面 1-5 类(概念解释 / 对比辨析 / 原理追问 / 场景排查 / 方案设计)是 building blocks——一块块拆开的知识点。 这份「系统串联题」凌驾于它们之上:每道题都是一个真实运维里反复出现的场景,一个问题能炸开成一整棵知识树,考官顺着追问一路深入。它把散落在 1-5 类里的知识点串成一条线,考的是你能不能把零件组装成系统级的排障/原理能力。
入选标准(三条同时满足 + 一条加分):
- 高杠杆——学会终身受用,真实运维反复用到;
- 高频必问——Linux 面试几乎跑不掉;
- 能串联——一题炸开成一棵知识树,区分度极高;
- 加分——每题都带「踩坑细节」,是"真做过"才知道的东西,不是教科书答案。
建议:考前把这 8 道当"总题"重点刷。能把每题的追问链顺下来,1-5 类的零散知识点自然就被盘活了。
发行版基线(2026):CentOS 7/8 均已 EOL,示例以 Rocky/AlmaLinux(RHEL 系)与 Ubuntu/Debian 系为准;网络工具统一用
ss/ip(不用netstat/ifconfig);服务管理用systemctl(不用service/chkconfig)。
锚点题 1:服务器 load 飙高 / CPU 打满 / 系统卡死,你怎么一步步定位?#
为什么是锚点题:这是 Linux 排障的"总题"。一问就能看出你是背命令还是真懂——真懂的人先分类(是 CPU 忙、I/O 卡、还是 softirq 打满),背命令的人上来就 top 然后卡壳。几乎每场运维/SRE 面试都会问。
会串出的知识点地图:
load 飙高 / 系统卡
├── load average 到底是什么(1/5/15 分钟)
│ └── Linux 特殊:load = 可运行(R) + 不可中断(D) 进程数 → load 高 ≠ CPU 忙
├── CPU 时间分解 us / sy / ni / id / wa / hi / si / st
│ ├── us 高 → 应用层 CPU(死循环 / 正则 / 加解密 / GC)
│ ├── sy 高 → 系统调用/上下文切换过多、fork 风暴
│ ├── wa 高 → I/O 瓶颈(磁盘慢 / 等 I/O)
│ ├── si 高 → 软中断(高 pps 网络、单核 softirq 打满)
│ └── st 高 → 云主机被"邻居"抢 CPU(超卖 / steal)
├── 进程 → 线程 → 调用栈 逐层下钻
├── D 态进程(不可中断睡眠)→ 卡在内核 I/O
└── 工具链:top/htop · uptime · vmstat · iostat · pidstat · mpstat · sar · perf · strace考官追问链:
- 现象层:怎么快速判断"到底是 CPU 忙、还是 I/O 卡、还是内存/网络"?(
uptime看 load,top看 CPU 那一行的分解) - 机制层:load average 的数字到底代表什么?为什么 load 很高但
top里%id(idle)还很大?(Linux 把 D 态也算进 load) - 边界层:
%wa高一定是磁盘的锅吗?%st高说明什么?(wa 是"CPU 空闲且有 I/O 在飞",st 是被虚拟化宿主抢走) - 定位/验证层:怎么从"某个 CPU 100%"下钻到"哪个进程→哪个线程→哪一行代码/哪个系统调用"?(
top -H/pidstat -t→perf top/strace/ 语言级jstack、py-spy)
参考答题骨架:
- 先分类(最关键的一步):
uptime看 load 和核数比(nproc拿核数,load/核数 ≈ 1 算满载);top看 CPU 行:us高 → 应用 CPU 密集 → 找进程找线程;sy高 → 系统调用/上下文切换多 →vmstat 1看cs(上下文切换)、in(中断);wa高 → I/O 瓶颈 → 转iostat -x 1(看%util、await、队列深度)+pidstat -d 1/iotop找是谁在读写;si高 → 软中断 →mpstat -P ALL 1看是不是某一核被打满、sar -n DEV 1看网卡 pps;st高 → 云主机被超卖,是宿主机/邻居的问题,不是你应用的锅。
- load 高但 CPU 空闲:几乎一定是 D 态进程堆积(卡 I/O)→
ps -eo state,pid,wchan,cmd | grep '^D',wchan看卡在哪个内核函数(多半是磁盘/NFS)。 - 下钻:找到进程 →
top -H -p <pid>或pidstat -t -p <pid> 1定位到热点线程 →perf top -p <pid>看热点函数 /strace -p <pid>看卡在哪个系统调用 / 语言层用jstack、py-spy dump抓栈。 - 兜底:
dmesg -T/journalctl -k看内核有没有报错(磁盘 I/O error、OOM、网卡 reset)。
踩坑 / 加分点:
- load 高 ≠ CPU 忙——这是最经典的坑。见过 load 几十、
%id却还 60% 的机器,真相是 D 态卡在挂死的 NFS 上。答出"load 含 D 态"直接拉开区分度。 top里进程%CPU可以 >100%——那是多线程按核累加(Irix 模式),按I键可切换成"整机百分比"。%wa高不代表 CPU 很忙,它是"CPU 空闲、但有未完成 I/O"的时间;wa 高时 CPU 其实可能很闲,别把 wa 当成"CPU 被 I/O 占用"。vmstat 1的第一行是开机以来的平均值,要看第二行起的实时值——好多人被第一行误导。- 云主机遇到
%st高,先甩锅给宿主超卖是对的,但要能拿出证据(st持续高 + 自己进程没那么忙)。
关联:CPU/进程状态细节见「原理追问型」进程调度部分;
top/vmstat/iostat逐命令见「网络诊断/存储」与「15-日志与排查思路」。
锚点题 2:磁盘明明有空间,却报 No space left on device,怎么回事?#
为什么是锚点题:df -h 看着还剩一大半,写文件却报"没空间"——这个反直觉现象几乎人人踩过,是检验"是否真管过生产机"的照妖镜。高频且高杠杆。
会串出的知识点地图:
No space left(但 df -h 有空间)
├── inode 耗尽 → df -i 看 IUse%(海量小文件:session/缓存/邮件队列)
├── 已删除但被进程占用 → lsof +L1 / lsof | grep deleted(du 和 df 对不上)
├── 文件系统预留块 → ext4 默认给 root 留 5%,普通用户先报满(tune2fs -m)
├── 写错了分区/挂载点 → df <目标路径> 确认到底落在哪个文件系统
├── 文件系统只读 → 出错后内核 remount ro(dmesg 有 EXT4-fs error)
└── 磁盘/项目配额 quota → quota -u / repquota考官追问链:
- 现象层:
df -h显示有空间,写入却报错,你第一反应查什么?(df -i——先排除 inode 耗尽) - 机制层:为什么会 inode 耗尽?inode 和 block 是两套独立计数吗?(是;ext4 建文件系统时 inode 数就定死了,海量小文件耗光 inode,block 还剩一堆)
- 边界层:
du -sh加起来远小于df显示的已用,差的空间去哪了?(被"已删除但仍被进程打开"的文件占着) - 定位/验证层:怎么找到并释放这些幽灵文件?删大日志正确姿势是什么?(
lsof +L1找 → reload/重启进程,或truncate -s 0;别用rm)
参考答题骨架:
- 第一刀:
df -i。IUse% 100% 就是 inode 耗尽——海量小文件(PHP session、缓存碎片、邮件队列、大量空文件)。定位大户:for d in /*; do echo "$(find $d -xdev 2>/dev/null | wc -l) $d"; done | sort -rn。 - 第二刀:
df -h有空间 +du -sh对不上 → 已删除文件被进程占用。lsof +L1(列出链接数<1 即已删仍打开的文件)或lsof | grep deleted。典型:日志被rm了但 nginx/tomcat 还在往那个 fd 写,空间死活不回来。- 解决:
systemctl reload/重启持有进程;或不重启就truncate -s 0 /proc/<pid>/fd/<n>清空。
- 解决:
- 再排查:预留块(
tune2fs -l看 Reserved block count,tune2fs -m 1调低);写错分区(df /path确认路径归属哪个文件系统);只读重挂(mount | grep ro+dmesg看有没有文件系统报错);配额(repquota -a)。
踩坑 / 加分点:
du和df对不上,99% 就是"已删除文件被进程占用"——这是本题最值钱的一句话。- 删满盘的大日志,正确姿势是
truncate -s 0 file或> file,绝不是rm。rm后进程还持有 fd,空间不释放,反而更难救。 - XFS 的 inode 是动态分配的,不像 ext4 建盘时定死,所以 XFS 上 inode 耗尽相对少见(但受
imaxpct限制,极端海量小文件仍可能撞上)。 - 别忘了
df -i——太多人只看df -h,空间够就懵在原地。 - 若报的是
Read-only file system而非No space,那是文件系统出错被内核保护性 remount ro 了,dmesg里能看到,方向完全不同。
关联:inode 本质见「概念解释型 题目1」;删文件为何不释放空间见本档「锚点题 5」。
锚点题 3:一个进程 kill -9 都杀不掉,为什么?怎么办?#
为什么是锚点题:kill -9 在很多人心里是"核武器、必杀"。能讲清楚它为什么也会失效,直接暴露你对进程状态和信号机制的理解深度。经典高区分度题。
会串出的知识点地图:
kill -9 杀不掉
├── SIGKILL(9) 语义:不可捕获/不可忽略/不可阻塞,但——
├── D 态(TASK_UNINTERRUPTIBLE)→ 卡在内核态 I/O,信号排队等它醒;NFS 挂死/磁盘坏 → 永远醒不来
├── 僵尸态 Z(defunct) → 进程已死,只剩退出状态等父进程回收;杀"死人"无效,要处理父进程
├── 内核线程([kworker] 等)→ 名字带方括号,不响应普通信号,也不该 kill
├── PID 1(systemd) → 内核特殊保护
└── T 态(被 ptrace/调试器 stop)→ 需先 detach / SIGCONT
│
└── 退出码:被信号 n 杀死 → $? = 128 + n(SIGKILL=137, SIGTERM=143, SIGSEGV=139)考官追问链:
- 现象层:
kill -9 <pid>敲了没反应,进程还在。你先看什么?(ps -o pid,stat,wchan,cmd——看 STAT 那一列) - 机制层:SIGKILL 不是"不可阻塞、必杀"吗?什么情况下它也不生效?(D 态收不到信号、僵尸已经是死的)
- 边界层:D 态和僵尸态处理方式一样吗?(完全不一样:D 态是"活着卡在内核",查 I/O;僵尸是"已死没人收尸",处理父进程)
- 定位/验证层:怎么确认它到底卡在哪?怎么救?被信号杀死后退出码是多少?(
cat /proc/<pid>/stack看内核栈;D 态修底层 I/O 或最后 reboot;僵尸 kill 父进程;$?=128+n)
参考答题骨架:
- 先确诊状态:
ps -eo pid,ppid,stat,wchan,cmd | grep <pid>,看 STAT 首字母:- D(不可中断睡眠):进程在内核态等 I/O(磁盘、NFS、某些驱动),信号只在返回用户态时处理,D 态收不到,SIGKILL 只能排队。若底层 I/O 永不返回(NFS server 宕、磁盘坏),进程永远 D 态。救法:修复底层 I/O(恢复存储/NFS/卸载卡死挂载),实在不行只能 reboot。
- Z / defunct(僵尸):进程已经死了,只剩一条 task_struct 保留退出状态,等父进程
wait()回收。对死人发信号没用。救法:让父进程去wait,或kill掉父进程——孤儿被 PID 1(systemd)收养并回收。 - 内核线程(
[kworker/*]、[ksoftirqd],名字带方括号):不是普通进程,不响应普通信号,也不该动。 - T(stopped):被调试器 ptrace 停住,先
kill -CONT或 detach。
- 退出码:进程被信号 n 终止,shell 里
$? = 128 + n。SIGKILL(9)→137,SIGTERM(15)→143,SIGSEGV(11)→139。反推能知道进程是被什么信号弄死的。 - 深挖卡点:
cat /proc/<pid>/stack(需权限)看内核调用栈,wchan看睡在哪个内核函数。
踩坑 / 加分点:
- "kill -9 杀不掉"90% 不是 D 态就是僵尸,而这两者处理天差地别(一个查 I/O、一个查/杀父进程),能一句话点破区别是加分点。
- 僵尸进程不占 CPU/内存,只占一个 PID 和进程表项;真正的危害是大量僵尸把 PID 耗尽。所以"僵尸多"要治的是那个不回收子进程的父进程。
- 别上来就
kill -9。正常流程先SIGTERM(15) 让进程优雅退出(flush 数据、清临时文件、释放锁)。直接 -9 可能留下脏数据、残留锁文件、半截写的文件。 - 有一种
TASK_KILLABLE是"可被 SIGKILL 打断的 D 态变种",较新的内核代码路径会用,所以不是所有 D 态都绝对杀不动——但老驱动/老路径不保证。
关联:进程状态机、信号完整列表见「09-进程管理」;退出码 128+n 也在「14-Shell脚本」里出现。
锚点题 4:从敲下一条命令到看到输出,中间发生了什么?#
为什么是锚点题:这是操作系统与 Linux 的"世纪之问",一句话能把 shell、进程、系统调用、权限模型全串起来。答得越细,功底越深,几乎是资深岗必问的分水岭题。
会串出的知识点地图:
敲 `ls -l /tmp > out.txt` 回车
├── shell 解析:分词 → 展开(alias→大括号→~→$变量→$()→算术→glob*→去引号) → 识别重定向 >
├── 命令类型判断:builtin(cd/echo) / 函数 / 外部程序(只有外部程序才走 PATH)
├── PATH 查找 + hash 缓存(hash -r 清)
├── fork() → 子进程(COW 写时复制,不真复制内存)
├── 子进程里做重定向:open(out.txt) → dup2(fd, 1)
├── execve() → 加载 ELF、ld.so 链接 .so、替换进程镜像(PID 不变)
├── 权限检查:文件 x 位 + 路径每级目录 x 位 + inode mode/uid/gid(含 SUID/SGID)
├── 运行:系统调用读目录(getdents)/取元数据(stat)/write(1,...) → 因 fd1 已重定向,写进文件
└── 退出:exit → 父进程 wait() 收尸拿 $?(前台还涉及 tty/进程组/会话/SIGCHLD)考官追问链:
- 现象层:回车之后,shell 第一步做什么?(读一行 → 词法分析/分词 → 一系列展开)
- 机制层:shell 怎么知道该跑哪个程序?内建命令和外部命令有什么区别?(builtin 不 fork,外部命令才查 PATH、fork+exec)
- 边界层:
> out.txt这个重定向,是在 fork 之前还是之后生效的?为什么不会污染当前 shell?(在子进程里、exec 之前做open+dup2,只影响子进程) - 定位/验证层:为什么有时候报 command not found,有时候报 Permission denied?怎么区分?(前者 PATH 里没有;后者找到了但没 x 位、或路径上某级目录没 x)
参考答题骨架:
- shell 阶段:读入一行 → 分词 → 按固定顺序展开(alias → 大括号
{}→ 波浪号~→ 变量$→ 命令替换$()→ 算术 → 路径通配*→ 去引号),同时识别重定向/管道。 - 定位命令:先判断是别名、shell 内建(
cd/export/echo)、还是函数;都不是才当外部程序,按$PATH顺序查找(有 hash 表缓存,hash -r清)。 - 创建进程:
fork()出子进程(COW 写时复制,不真复制父进程内存,因为马上要 exec)。 - 子进程里配重定向:
open("out.txt", O_WRONLY|O_CREAT|O_TRUNC)拿到 fd,dup2(fd, 1)把 stdout 指到文件。管道则是pipe()把多个进程的 fd 串起来。 - execve:加载 ELF,动态链接器
ld.so加载依赖的共享库(ldd可看),映射地址空间,进程镜像被替换但 PID 不变。 - 权限检查:执行需文件
x位;进入/tmp需路径上每一级目录的x(穿过)位;读目录内容需r位;内核按 inode 的 mode + owner/group 对你的 euid/egid 判定(SUID/SGID 会改变有效身份)。 - 运行与收尾:
ls通过系统调用openat/getdents读目录、stat取元数据、write(1, ...)输出——因 fd 1 已被重定向,内容落进out.txt;进程exit(),shellwait()/waitpid()收尸拿到$?。
踩坑 / 加分点:
fork用 COW,不是立刻复制整个内存——因为紧接着就exec把镜像换掉了,复制开销近乎白费。能提vfork/posix_spawn优化更佳。- 重定向的
open+dup2发生在 fork 之后、exec 之前的子进程里——所以只对被执行的命令生效,不会污染当前 shell 的 stdout。 command not foundvsPermission denied要能区分:前者 = PATH 里根本没这个可执行文件;后者 = 找到了但没x位,或路径上某级目录缺x(进不去)。- 目录的
x位是"能否进入/穿过",r位是"能否列出内容"——只有r没x,能看到文件名但stat不了(ls -l全是问号)。这点极多人搞混。 - 内建命令为什么不能是外部程序:
cd必须改当前 shell 的工作目录,如果 fork 出子进程去 cd,改的是子进程的目录,父 shell 根本不变——所以cd天生只能是 builtin。 hash缓存会导致你更新/移动了二进制后 shell 还跑旧路径,hash -r刷新。
关联:展开顺序/引号见「14-Shell脚本」;重定向与管道见「08-管道与重定向」;权限位见「04-权限系统」。
锚点题 5:一个文件/目录删不掉,或删了空间没释放,排查思路?#
为什么是锚点题:删文件看似最基础,却藏着一堆反直觉的坑(删权限看的是父目录、chattr 锁、幽灵文件占空间)。一道题把权限模型、inode/硬链接、文件系统状态全串起来,高频且能问很深。
会串出的知识点地图:
文件删不掉 / 删了空间不释放
├── 权限:能删与否看【父目录】的 w+x,不是文件本身!
│ └── sticky bit(+t,如 /tmp 的 1777):只有属主/root 能删
├── inode 与硬链接计数:unlink 只是 i_nlink -1;=0 且无进程打开 才真正释放数据块
├── 删了空间不释放:i_nlink=0 但进程还持有 fd(deleted 状态)→ lsof +L1
├── 特殊删不掉
│ ├── chattr +i 不可变属性(root 也删不掉)→ lsattr 查、chattr -i 解
│ ├── 文件名含特殊字符/前导 - → rm ./-x 或 find -inum <n> -delete
│ ├── 文件系统只读/损坏 → dmesg,先修复/重挂
│ └── 目录 device busy → 有进程 cwd/占用:lsof +D / fuser -vm考官追问链:
- 现象层:普通用户能不能删掉一个属主是 root、权限 000 的文件?(能——只要你对父目录有 w+x)
- 机制层:为什么删权限看父目录而不是文件本身?
rm到底删了什么?(rm=unlink目录项,改的是目录内容,所以要目录的写权限) - 边界层:
rm完文件、i_nlink到 0 了,为什么df空间还没回来?(还有进程持有该文件的 fd,数据块不释放) - 定位/验证层:
root都删不掉一个文件,可能是什么原因?怎么查?(chattr +i不可变属性 / 文件系统只读 / device busy——lsattr、dmesg、lsof +D)
参考答题骨架:
- 权限的真相:
rm本质是unlink——从父目录里删掉目录项。所以能不能删,取决于你对父目录有没有w+x,跟文件本身权限无关(文件 000/只读也照删)。 - sticky bit:目录设了
+t(如/tmp的1777),则只有文件属主、目录属主或 root 能删——防止公共目录里互删。 - inode 与硬链接:
ls -i看 inode 号,stat看 Links 数。unlink只是把链接计数减 1;只有链接数=0 且没有进程打开该文件时,数据块才真正释放。 - 删了空间不释放:链接数已到 0,但进程还持有 fd → 幽灵文件。
lsof +L1/lsof | grep deleted找 → reload/重启进程,或truncate -s 0 /proc/<pid>/fd/<n>。(同「锚点题 2」) - root 都删不掉:
chattr +i(immutable):连 root 都改不了删不了,lsattr查、chattr -i先解锁;- 文件名含空格/控制字符/前导
-:rm ./-file、rm -- -file,或按 inode 删find . -inum <n> -delete; - 文件系统只读/损坏:
dmesg看 EXT4/XFS error,先fsck/重挂读写; - 删目录报
Device or resource busy:有进程 cwd 在里面或打开了文件,lsof +D /path/fuser -vm /path找出来。
踩坑 / 加分点:
- "文件是 root 的、权限 000,我普通用户能删吗?"——能! 只要对父目录有 w+x。这题极爱考,答"不能"直接挂,因为暴露了你不懂"删权限看父目录"。
chattr +i是运维加固手段,也是黑客锁后门文件的常用招。遇到 root 都删不掉的文件,先lsattr看属性——很多人卡这里半天想不到。- 删满目录的大日志空间不回收 →
truncate而非rm(进程持有 fd 时)。 - 海量小文件
rm -rf很慢(逐个 unlink + 遍历目录)。可用rsync --delete拿空目录去覆盖,或极端情况直接重建文件系统更快。 - NFS 上删正在被打开的文件会留下
.nfsXXXX(silly rename),关掉持有进程即可。
关联:inode/硬链接见「概念解释型 题目1、2」与「原理追问型 题目6」;权限位见「04-权限系统」;空间不释放见本档「锚点题 2」。
锚点题 6:内存去哪了?free 里的 buffer/cache 是什么,OOM 是怎么触发的?#
为什么是锚点题:free 看着"内存快满了"其实是新手最大误判来源。能讲清 buff/cache 可回收、available 才是真相、以及 OOM Killer 的选择逻辑,是内存这块的分水岭题。容器时代(cgroup 限制)更是必问。
会串出的知识点地图:
内存去哪了
├── free 各列:total/used/free/shared/buff/cache/available
│ ├── buff/cache = 页缓存,可回收,不是真占用
│ └── available 才是应用真正还能用的(含可回收 cache)← 看这个,不是 free 列
├── 进程视角:RES(真实物理) vs VIRT(虚拟地址空间,别被吓到) vs SHR,更准用 smaps 的 Pss
├── 内核占用:slabtop(dentry/inode 缓存,海量小文件会撑大)
├── swap:vmstat 的 si/so,频繁换入换出 = thrashing = 系统假死般卡
└── OOM Killer:物理+swap 都不够又回收不了 → 按 oom_score 选进程杀
└── cgroup(容器/systemd) 内存超限 → cgroup 级 OOM,只杀该组内进程考官追问链:
- 现象层:
free -h显示 free 只剩几百 M,是不是内存快满要出事了?(不一定——buff/cache 可回收,看available) - 机制层:buff/cache 是什么?为什么 Linux 要把空闲内存拿去做 cache?(页缓存加速文件 I/O;"空闲内存是浪费",内存吃紧时自动回收)
- 边界层:进程 VIRT 几十 G 是不是吃了几十 G 内存?RES 和 Pss 有什么区别?(VIRT 是虚拟地址空间,未必占物理;看 RES,共享库重复计要看 Pss)
- 定位/验证层:进程被莫名杀了,怎么确认是 OOM?容器里内存明明够却被杀是为什么?(
dmesg/journalctl -k找 "Out of memory: Killed process";容器按 cgroupmemory.max算,不是宿主总内存)
参考答题骨架:
- 看
free -h的正确姿势:别盯free列,看available——它估算了"包含可回收 cache 在内、应用还能拿到多少"。buff/cache是内核用空闲内存做的页缓存,内存紧张时会自动回收,不算真占用。 - 定位 used 高:
top按内存排序(大写M)或ps aux --sort=-rss。看 RES(常驻物理内存),别看 VIRT(虚拟地址空间,含未落地的映射)。更精确用/proc/<pid>/smaps_rollup里的 Pss(共享库按比例分摊,RSS 会重复计)。 - 内核内存:
slabtop看 slab(dentry/inode 缓存),遍历海量小文件会把 dentry cache 撑很大。 - swap:
swapon --show+vmstat 1看si/so。持续换入换出 = thrashing,系统卡到"假死"——这种时候往往宁可让它 OOM 也别长期抖。 - OOM Killer:物理内存 + swap 都不够、又回收不出来时触发。内核按
oom_score(受oom_score_adj调节)挑"性价比最高"的进程杀(通常是占内存最大的)。证据在dmesg -T/journalctl -k:Out of memory: Killed process <pid> (<name>)。 - 容器/cgroup:容器内存超
memory.max会触发 cgroup 级 OOM,只杀该 cgroup 内进程。看memory.events(oom_kill 计数)。
踩坑 / 加分点:
- 只看
free列以为要爆、其实 buff/cache 可回收——最经典误判。一句"看 available"立刻显专业。(很老的 procps 没有 available 列,更容易被坑。) - VIRT 大 ≠ 吃内存:JVM 预留地址空间、
mmap大文件都会让 VIRT 巨大但 RES 不高。看 RES/Pss。 - 容器里
free/top看到的常是宿主机内存(除非新内核 + cgroup v2 感知),真正限制是memory.max,OOM 也按 cgroup 算——"容器被 OOM 但宿主内存够"的坑就在这。排查容器内存必看 cgroup。 echo 3 > /proc/sys/vm/drop_caches能手动放 cache,但生产别乱用:下次读全 miss,性能抖动,一般根本不需要。- OOM 杀的不一定是元凶:内核挑的是"占最多"的进程,真凶可能是那个疯狂申请内存、触发了这次分配的进程。别看到谁被杀就怪谁。
关联:内存概念/swap 见「概念解释型」;
top/free/vmstat命令见「09-进程管理」「15-日志与排查思路」。
锚点题 7:SSH 连不上服务器,给我一套完整的排查思路?#
为什么是锚点题:几乎人人被 SSH 卡过,而它天然串起"网络分层 + 服务 + 认证 + 权限 + SELinux + 磁盘"一整条链,是检验"分层排障思维"的最佳载体。运维面试的常青题。
会串出的知识点地图:
SSH 连不上(按连接建立顺序自下而上)
├── 网络可达:ping / 路由(ICMP 可能被禁)
├── 名字解析:dig / getent hosts(连错 IP?)
├── 端口可达:服务端 ss -tlnp|grep :22(监听在 0.0.0.0 还是 127.0.0.1?)
│ └── refused(端到了没人听/被 reset) vs timeout(包被防火墙丢)← 分水岭
├── 防火墙/安全组:firewalld/nftables/iptables + 云安全组(timeout 常在这层)
├── sshd 服务:systemctl status sshd / journalctl -u sshd
├── 认证层
│ ├── ~/.ssh 700、authorized_keys 600、家目录不可组/他人可写(StrictModes)← 最高频坑
│ ├── sshd_config:PubkeyAuthentication/PasswordAuthentication/PermitRootLogin/AllowUsers
│ ├── 客户端 ssh -vvv 看协商断在哪一步
│ └── SELinux:authorized_keys context 不对 → restorecon(Rocky/Alma 坑)
└── 其它:磁盘满、hosts.deny、MaxStartups 限流、shell 是 /sbin/nologin、家目录不存在考官追问链:
- 现象层:连不上有两种表现——
Connection refused和Connection timed out,它们指向的问题一样吗?(完全不同!refused=通到主机了、端口没服务/被拒;timeout=包被丢,一般防火墙/安全组/路由) - 机制层:怎么确认 sshd 真的在监听、监听在哪个地址?(服务端
ss -tlnp | grep :22,看是0.0.0.0还是127.0.0.1——后者只能本机连) - 边界层:密钥登录一直失败、回退到要密码,最可能是什么?(
~/.ssh或家目录权限太开,sshd因 StrictModes 静默拒绝公钥) - 定位/验证层:怎么快速定位卡在哪一步?看哪些日志?(客户端
ssh -vvv;服务端journalctl -u sshd+ RHEL 系/var/log/secure或 Debian 系/var/log/auth.log)
参考答题骨架:
- 分层,从下往上:
- 网络可达:
ping(ICMP 可能被禁,不通不代表死)、路由; - 解析:连域名时
dig/getent hosts确认没连错 IP; - 端口:服务端
ss -tlnp | grep :22看 sshd 监听没、监听在哪个地址(0.0.0.0全网 /127.0.0.1仅本机 / 特定 IP);客户端nc -vz host 22测通不通; - 防火墙/安全组:本机
nft list ruleset/iptables -L -n+ 云安全组; - 服务:
systemctl status sshd、journalctl -u sshd(配置写错会启动失败); - 认证:公钥登录严查权限——
~/.ssh700、authorized_keys600、家目录不能对组/其他人可写(否则 StrictModes 拒绝);sshd_config的PubkeyAuthentication/PasswordAuthentication/PermitRootLogin/AllowUsers;客户端ssh -vvv逐步看协商。
- 网络可达:
- 最有用的两个动作:客户端
ssh -vvv看断在哪一步 + 服务端看 sshd 日志,两边对照。
踩坑 / 加分点:
refusedvstimeout是排查方向的分水岭:refused = 已通到主机、是端口/应用层问题(sshd 没起、监听地址不对);timeout = 包被丢、往防火墙/安全组/路由查。答出这个区别立刻显功底。- 公钥登录失败 90% 是
~/.ssh或家目录权限太开(StrictModes)。家目录 777、.ssh组可写都会让 sshd 静默拒绝公钥、回退密码,看着像"密钥没生效"。 - Rocky/Alma/RHEL 系 vs Ubuntu/Debian 系差异是坑:日志前者在
/var/log/secure+ 有 SELinux(authorized_keyscontext 不对要restorecon -Rv ~/.ssh),后者在/var/log/auth.log+ 无 SELinux(有 AppArmor)。 /或/var、/tmp磁盘满会让 SSH 登录失败或卡住(建不了会话、写不了 utmp/临时文件)——一个"看似认证问题"其实是磁盘满的经典串联坑。- 别只在客户端瞎试,一定上服务器看 sshd 日志和
ss监听,否则永远在猜。
关联:本题在「场景排查型 题目1」有决策树版;
ss/nc/防火墙命令见「11-网络诊断工具」。
锚点题 8:服务器从按下电源到出登录界面,中间发生了什么?#
为什么是锚点题:和「命令到输出」并列的两大"全过程"题。它把固件、引导、内核、initramfs、systemd 依赖体系全串起来,还直接连到"开机卡住/进不去系统怎么救"的实战。资深运维必问。
会串出的知识点地图:
上电 → 登录界面
├── 固件 BIOS/UEFI:POST 自检 → 找启动设备(UEFI 读 ESP 的 .efi / BIOS 读 MBR)
├── Bootloader GRUB2:读 grub.cfg → 加载 vmlinuz + initramfs → 传内核参数(root=UUID..., ro)
├── 内核:解压初始化 → 挂 initramfs 当临时根
├── initramfs:装 LVM/RAID/LUKS/NVMe 等驱动 → 挂真正的根(先只读) → switch_root 切真根
├── systemd (PID 1):按 target 拉服务
│ ├── get-default(multi-user 命令行 / graphical 图形)
│ ├── 按 Wants/Requires/After/Before 解析依赖,能并行就并行
│ └── sysinit → basic → multi-user →(graphical):挂 fstab、起网络/日志/sshd
└── 登录:命令行 getty→login→PAM / 图形 gdm|sddm→桌面会话考官追问链:
- 现象层:开机大致分几个阶段?谁是第一个用户态进程?(固件→GRUB→内核→initramfs→systemd;PID 1 = systemd)
- 机制层:initramfs 是干嘛的、为什么需要它?(里面装了挂载真正根文件系统所需的驱动/模块,比如根在 LVM/RAID/加密盘/NVMe/NFS 上)
- 边界层:systemd 怎么决定服务启动顺序、为什么比老 SysV 快?(按 Wants/Requires + After/Before 解析依赖,无依赖的并行启动,不像 SysV 顺序跑脚本)
- 定位/验证层:开机很慢/卡住怎么排查?根挂不上掉进哪里、怎么救?(
systemd-analyze blame/critical-chain、journalctl -b;根挂载失败掉进 initramfs/dracut 应急 shell,GRUB 里加systemd.unit=rescue.target)
参考答题骨架:
- 固件:BIOS/UEFI 上电自检(POST),初始化硬件,按启动顺序找设备——UEFI 从 ESP(EFI 系统分区)读
.efi引导程序,BIOS 从 MBR 读引导代码。 - Bootloader(GRUB2):读
grub.cfg,加载选定的内核vmlinuz和initramfs到内存,传内核命令行参数(root=UUID=...、ro等)。 - 内核:解压、初始化,挂
initramfs作为临时的内存根。 - initramfs:一个精简根环境,装着"挂载真正根文件系统"所需的驱动/模块(LVM、软 RAID、LUKS 加密、NVMe、根在 NFS 等)。加载驱动 → 找到并挂载真正的根(先只读)→
switch_root/pivot_root切到真根。 - systemd(PID 1):接管系统,按 target 拉起服务。默认 target 由
systemctl get-default决定(multi-user.target命令行 /graphical.target图形)。按Wants/Requires+After/Before解析依赖,能并行的并行启动。关键链:sysinit → basic → multi-user →(graphical),其间挂载/etc/fstab、起网络、日志、sshd 等。 - 登录:命令行由
getty/agetty起login提示 + PAM 认证;图形由 display-manager(gdm/sddm)接管 → 登录 → 桌面会话。 - 排查/验证:
systemd-analyze(总耗时)、systemd-analyze blame(哪个服务拖慢)、systemd-analyze critical-chain(关键路径);journalctl -b(本次启动)、-b -1(上次)、-p err -b(只看错误)。开机卡住 → 进 GRUB 编辑内核参数(去掉rhgb quiet看详细,或加systemd.unit=rescue.target/emergency.target进救援)。
踩坑 / 加分点:
- 别再背 SysV init/
/etc/inittab/runlevel 那套。2026 的 Rocky/Alma/Ubuntu 早就是 systemd + GRUB2,用systemctl(不是service/chkconfig,虽有兼容层)。runlevel↔target 映射记一下:3=multi-user、5=graphical。 - initramfs 里缺正确的存储驱动 → 根挂不上、直接开不了机——硬件迁移、P2V、内核升级后是高频事故。重建:RHEL 系
dracut -f,Debian 系update-initramfs -u。 - 别手改
grub.cfg:改/etc/default/grub后再生成——RHEL 系grub2-mkconfig -o /boot/grub2/grub.cfg,Debian 系update-grub。 - UEFI vs BIOS 引导机制不同(ESP/
efibootmgrvs MBR),装系统/修引导时启动方式搞错是经典坑。 systemd-analyze blame会把network-online这类"等待型"服务算进去,容易误伤——判断真正瓶颈要看critical-chain(关键路径),而不是单看 blame 排行。
关联:systemd 单元/依赖/target 见「13-服务管理systemd」;
journalctl用法见「15-日志与排查思路」。