面试 · 对比辨析型
考察目标:精确区分相似概念,能对比分析 18 题,每题含对比表
题目1:硬链接 vs 软链接(symlink)#
| 维度 | 硬链接 | 软链接 |
|---|---|---|
| 本质 | 同一 inode 的不同目录项 | 独立文件,存目标路径 |
| 跨文件系统 | ❌ | ✅ |
| 链目录 | ❌ | ✅ |
| 删源文件后 | 数据仍存在 | 断链(dangling symlink) |
| inode 号 | 相同 | 不同 |
| 链计数 | +1 | 不变 |
| 创建命令 | ln target link | ln -s target link |
选型:配置管理(sites-enabled → sites-available)用软链接;增量备份(rsync --link-dest)用硬链接去重。
底层实现(
i_nlink/S_IFLNK/ 为何硬链接不能跨文件系统、不能链目录)见「原理追问型 题目6」。
题目2:进程状态 S vs D#
| 维度 | S (Interruptible Sleep) | D (Uninterruptible Sleep) |
|---|---|---|
| 含义 | 等待事件,可被信号唤醒 | 等待内核 IO,不可中断 |
| kill -9 有效 | ✅ | ❌ |
| 典型原因 | select/epoll 等待 | NFS 挂载卡住、磁盘 IO 超时 |
| 信号处理 | 收到信号立即返回 EINTR | 信号挂起直到 IO 完成 |
| K8s 影响 | Pod 正常终止 | Pod 卡在 Terminating |
关键差异:D 状态不等于"进程坏了",它是内核 IO 路径的正常状态,但长时间 D 状态就是故障(存储/NFS 不可达)。
题目3:su vs sudo#
| 维度 | su | sudo |
|---|---|---|
| 方式 | 切换到 root 用户 | 以 root 权限执行单条命令 |
| 需要知道 | root 密码 | 用户自己的密码 |
| 审计 | 无日志(谁用 root 做了什么) | 详细日志(/var/log/auth.log) |
| 权限粒度 | 全部 root 权限 | 可按用户/命令粒度授权 |
| 生产推荐 | ❌ | ✅ |
sudo 通过 /etc/sudoers(visudo 编辑)支持精细化控制:deploy ALL=(root) /bin/systemctl restart myapp 只允许 deploy 用户重启 myapp。
题目4:TCP vs UDP#
| 维度 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 确认/重传/顺序保证 | 尽最大努力,不保证 |
| 延迟 | 较高(握手+确认开销) | 低 |
| 流控 | 拥塞控制+流量控制 | 无 |
| 典型应用 | HTTP/SSH/MySQL | DNS/NTP/视频流/VXLAN |
在运维中:监控系统(Prometheus Pull 用 TCP)、日志传输(syslog 可用 UDP 牺牲可靠性换性能)、容器网络(VXLAN 用 UDP 封装)。
题目5:iptables vs nftables#
| 维度 | iptables | nftables |
|---|---|---|
| 推出时间 | 1999 | 2014(内核 3.13) |
| 规则组织 | 4 表 5 链,按表独立管理 | 统一框架,inet 表 |
| 性能 | O(n) 线性遍历 | O(log n) set + map |
| 原子规则更新 | 不原生支持 | 原生支持 |
| 语法 | 复杂的 iptables 命令 | 更接近配置文件语法 |
| 内核版本 | 所有版本支持 | 3.13+,4.0+ 生产就绪 |
| 未来 | 维护模式 | 替代 iptables |
K8s 中 kube-proxy iptables 模式在大规模集群(>1000 Service)性能下降严重,建议迁移到 IPVS 模式或 Cilium ebpf。nftables 正在被 Cilium/Calico 等 CNI 采用。
题目6:LVM 传统分区 vs 直接分区#
| 维度 | LVM | 传统分区 |
|---|---|---|
| 在线扩容 | ✅ lvextend + resize2fs | ❌ 需卸载分区 |
| 跨磁盘 | ✅ 可跨多块物理盘 | ❌ 一块盘一个分区 |
| 快照 | ✅ | ❌ |
| 性能损耗 | 微乎其微 (<1%) | 无 |
| 复杂度 | 三层抽象 (PV/VG/LV) | 直接 |
生产推荐:数据盘用 LVM(方便扩容),根分区视场景——AWS/Aliyun 的 EBS/云盘自带扩容能力,通常不需要 LVM。
题目7:ext4 vs xfs#
| 维度 | ext4 | xfs |
|---|---|---|
| 最大文件 | 16TB | 8EB |
| 大文件性能 | 中等 | 极好 |
| 小文件性能 | 好 | 好 |
| 创建速度 | 快 | 极快(只写元数据) |
| 缩容 | ✅ 但须卸载离线 resize2fs | ❌ 完全不支持 |
| 在线扩容 | ✅ resize2fs | ✅ xfs_growfs |
| 碎片 | 少 | 较多 |
| 默认 | Debian/Ubuntu | RHEL/Rocky/Alma 8·9、AWS AL2(CentOS 7 已 2024-06 EOL) |
K8s 节点和数据盘推荐 xfs。ext4 更适合小文件密集的负载(如 Git 仓库),且是唯一能缩容的主流选择(缩容须卸载离线操作)。扩容命令:ext4 用 resize2fs、xfs 用 xfs_growfs(xfs 只能变大)。
题目8:dd vs rsync vs scp#
| 维度 | dd | rsync | scp |
|---|---|---|---|
| 用途 | 块级复制 | 文件增量同步 | 文件远程传输 |
| 增量 | ❌ | ✅(只传差异) | ❌ |
| 跨机器 | ❌(可管道组合) | ✅ | ✅ |
| 压缩 | ❌ | ✅ (-z) | ✅ (-C) |
| 断点续传 | ❌ | ✅ (--partial) | ❌ |
| 典型场景 | 磁盘克隆/备份ISO | 备份/文件同步 | 单次传输 |
运维建议:日常备份用 rsync(增量节省带宽),紧急恢复用 scp(简单快速),dd 用于磁盘级操作。
题目9:grep vs sed vs awk#
| 维度 | grep | sed | awk |
|---|---|---|---|
| 用途 | 搜索文本 | 流编辑(替换/删除) | 结构化处理(列/统计) |
| 输出 | 匹配的行 | 修改后的文本 | 自定义字段/报表 |
| 计算能力 | ❌ | ❌ | ✅(算术/聚合) |
| 编程能力 | 正则 | 正则+简单逻辑 | 完整的脚本语言 |
| 典型命令 | grep ERROR log | sed 's/foo/bar/g' | awk '{print $1, $NF}' |
管道组合是它们真正威力:grep ERROR | awk '{print $5}' | sort | uniq -c | sort -rn — 找出出现最多的错误 IP。
题目10:ps aux vs ps -ef#
| 维度 | ps aux | ps -ef |
|---|---|---|
| 风格 | BSD | System V |
| 输出列 | USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND | UID PID PPID C STIME TTY TIME CMD |
| PPID | ❌ | ✅ |
| 完整性 | 较全 | 较全 |
| 常用 | Ubuntu/Debian 习惯 | RHEL/CentOS 习惯 |
两者都显示所有进程,习惯哪个用哪个。ps auxf 或 ps -ef --forest 可以显示进程树(父子关系)。
题目11:nohup vs disown vs tmux/screen#
| 维度 | nohup | disown | tmux/screen |
|---|---|---|---|
| 方式 | 启动时忽略 HUP 信号 | 启动后将进程从 jobs 移除 | 持久化终端会话 |
| 前提 | 启动时使用 | 已启动的进程 | 启动 tmux 后在其中运行 |
| 可重新连接 | ❌ | ❌ | ✅ |
| 查看输出 | 读 nohup.out | ❌ | 重连后直接看 |
| 适用场景 | 提前知道的长时间任务 | 忘记加 nohup 的补救 | 交互式长期会话 |
运维推荐:重要操作始终在 tmux 中执行,操作未完成不关 tmux 会话。
题目12:top vs htop vs atop#
| 维度 | top | htop | atop |
|---|---|---|---|
| 界面 | 纯文本,交互有限 | 彩色,鼠标支持,树状进程 | 纯文本,历史回放 |
| 历史数据 | ❌ | ❌ | ✅(可回放) |
| 安装 | 默认自带 | 需安装 | 需安装 |
| 资源消耗 | 最小 | 小 | 中等(写日志) |
| 适合 | 快速查看 | 日常交互分析 | 事后性能分析 |
运维场景:日常用 htop,事后分析用 atop(自带 sar-like 历史记录),脚本监控用 top -b -n 1 或直接 cat /proc。
题目13:df vs du 为什么数据不一致?#
| 维度 | df | du |
|---|---|---|
| 查看对象 | 文件系统元数据(超级块) | 逐目录递归统计文件大小 |
| 是否算已删除但未释放 | 算(inode 没释放) | 不算(文件已无路径) |
| 速度 | 快(只读超级块) | 慢(需要遍历) |
不一致的根因:df -h 显示磁盘已满,du -sh /* 加起来远小于 df 的值 → 进程持有已删除文件句柄。lsof | grep deleted 定位这些幽灵文件。
题目14:nslookup vs dig vs host#
| 维度 | nslookup | dig | host |
|---|---|---|---|
| 功能 | 基础查询 | 详细解析 + 追踪 | 简洁查询 |
| 输出 | 简单 | 详细(含查询统计) | 极简 |
| 脚本友好 | ❌ | ✅ (+short) | ✅ |
| 安装 | bind-utils | bind-utils | bind-utils |
运维推荐:排障用 dig(输出完整),脚本用 dig +short 或 host。
题目15:SIGTERM vs SIGKILL vs SIGHUP#
| 维度 | SIGTERM (15) | SIGKILL (9) | SIGHUP (1) |
|---|---|---|---|
| 能否捕获 | ✅ | ❌ | ✅ |
| 默认行为 | 退出 | 强制退出 | 退出 |
| 优雅退出 | ✅ | ❌ | ✅(如果程序实现了 reload) |
| 使用场景 | 正常停止服务 | 进程卡死不响应 | 重载配置 |
K8s Pod 停止:先发 SIGTERM → 等 terminationGracePeriodSeconds → 超时发 SIGKILL。应用应捕获 SIGTERM 做 graceful shutdown(关连接池、flush 日志、标记从 Service 摘除)。
题目16:[ ] vs [[ ]](test vs 扩展测试)#
| 维度 | [ ] / test(POSIX) | [[ ]](Bash/Ksh/Zsh 关键字) |
|---|---|---|
| 本质 | 外部命令语义 | shell 关键字(解析期处理) |
| 未加引号的变量 | 会词分割 + 通配符展开,空值/含空格直接语法错 | 不做词分割,[[ $x = y ]] 安全 |
| 逻辑运算 | -a / -o(已弃用、易歧义) | && / || |
| 字符串匹配 | 只能 =(精确) | == 支持通配、=~ 支持正则 |
| 数值比较 | -eq -lt … | -eq 也可,或 (( )) 更直观 |
| 可移植性 | POSIX sh 通用 | Bash 专有(#!/bin/sh 下不可用) |
经典坑:[ $x = "y" ] 当 $x 为空或含空格时报 unary operator expected;改成 [[ $x = "y" ]],或给 [ ] 里的变量加引号 [ "$x" = "y" ] 才安全。写 Bash 脚本优先 [[ ]];写要跑在 dash/ash 的 #!/bin/sh 脚本只能用 [ ]。
题目17:cron vs systemd timer#
| 维度 | cron | systemd timer |
|---|---|---|
| 配置 | crontab -e / /etc/cron.d | .timer + .service 成对 |
| 时间精度 | 分钟级 | 秒级,支持 OnCalendar、单调时钟 OnBootSec/OnUnitActiveSec |
| 日志 | 各发行版分散(syslog/cron.log) | 统一进 journal,journalctl -u x.timer |
| 错过补跑 | ❌(关机期间到点的任务丢失) | ✅ Persistent=true 开机补跑 |
| 打散负载 | 需手写随机 sleep | RandomizedDelaySec= 原生抖动 |
| 资源限制/依赖 | 无 | 继承 systemd(cgroup 限额、After=/Requires= 依赖) |
| 环境 | 极简 PATH,最常踩坑 | 显式 Environment=,行为可预期 |
选型:简单周期任务 cron 够用、可移植;需要精确调度、错过补跑、资源隔离、和 journal 统一观测时用 timer。查看所有定时器:systemctl list-timers --all。
题目18:netstat/ifconfig(net-tools)vs ss/ip(iproute2)#
| 旧命令(net-tools,已弃用) | 新命令(iproute2,现代默认) |
|---|---|
netstat -tlnp | ss -tlnp |
netstat -s | ss -s |
ifconfig | ip addr / ip -br a |
ifconfig eth0 up | ip link set eth0 up |
route -n | ip route |
arp -a | ip neigh |
为什么弃用:net-tools 自 2011 年起基本停止开发,很多新内核特性(多路由表、策略路由、部分 socket 状态)它看不到;且 netstat 靠遍历 /proc/net/* 解析,连接数一多就明显慢,ss 直接走 netlink 快得多。多数发行版(RHEL 8+/Debian 12+ 的最小安装)默认已不装 net-tools——别在文档/脚本里依赖 netstat/ifconfig。
小结#
对比辨析题的关键是"不只是列区别,而是说清楚为什么有这样的区别、各自适合什么场景"。Linux 中很多对比关系承载着设计决策和历史演进(如 iptables→nftables、SysV→systemd、ext4→xfs),能在对比中展现对 Linux 演进的理解是加分项。