2657 字
13 分钟
Linux 场景题

CPU / 内存#

内存泄漏如何排查?#

思路:遵循 “自上而下+工具链” 的思路

  1. 确认现象:用 free -havailable 是否持续走低,用 vmstat 1si/so 是否频繁交换。
  2. 定位进程:用 ps aux --sort=-%mem | head -n 10topM 排序,找到内存占用最高的 PID。
  3. 深入分析(按语言选工具)
    • Java 应用:用 jmap -dump 导出堆转储,配合 MAT 分析支配树和 GC Roots 引用链,定位泄漏对象。
    • C/C++ 应用:可用 memleak (eBPF) 追踪未释放的分配调用栈,或 valgrind 在测试环境分析。
  4. 判断类型:结合 GC 日志判断是堆内存泄漏、元空间泄漏还是直接内存泄漏,再针对性修复

服务器CPU使用率飙升,如何排查?#

思路:遵循 “自上而下+工具链” 的思路

标准排查流程:系统级/进程→线程→栈→系统调用

  1. 系统级分析topP 排序,或ps aux --sort=-%cpu | head -n 10,找到 %CPU 最高的异常进程 PID。
    • 使用 vmstat 1 观察 r(运行队列)是否长时间大于CPU核数,若 sy(内核态占用)飙升,可能是有频繁的上下文切换或中断。
    • 排查是否遭受了 DDoS/恶意攻击(大量握手请求占满CPU软中断 si)。
  2. 转为线程级分析
    • 执行 top -H -p [PID] 找出该进程内最耗CPU的线程ID(十进制)。(-H 显示详细线程,-p 指定PID)
    • 将线程ID转换为16进制:printf "%x\n" [线程ID]
  3. 抓线程栈
    • JAVA:使用 jstack [PID] | grep -A 20 [16进制线程ID] 直接查看该线程正在执行的代码堆栈,定位到具体类和方法。
    • 使用 perf top -p [PID] 查看 CPU 在执行哪些内核/用户态函数,精细定位热点函数(如垃圾回收GC线程,或者正则计算)
  4. 系统调用:如果栈显示卡在 read/write/futex 等,使用 strace -p [PID] 跟踪进程的系统调用,看是否卡在某个内核调用上(如不断重复读写文件)。

服务器频繁发生 OOM Kill,但业务进程内存占用并不高,如何排查?#

根因:通常是 内核 slab 内存(内核缓存)暴涨某个进程疯狂申请匿名内存页(如内存泄漏)但被漏看

排查步骤

  1. dmesg -T | grep -i "Out of memory" 查看 OOM 发生时被杀的进程名和 oom_score
  2. 查看系统内存细分:cat /proc/meminfo 关注 SlabSReclaimableKernelStack。若 Slab 异常大,用 slabtop 看是哪个内核对象占用(如 dentryinode_cache 暴涨,说明文件句柄泄露)。
  3. 统计所有进程实际占用总和:ps aux | awk '{sum+=$6} END {print sum/1024 " MB"}'(单位 KB),若总和远小于总内存,差值就是内核占用了。
  4. 检查是否有 内存超卖 情况(如 K8s Pod 的 limits 设置过小,虽然物理内存够,但 cgroup 限制内 OOM)。
  5. vmstat -s 查看 pages paged in/out,确认是否有频繁换页加剧内存压力。

服务器负载(Load Average)飙升,但 CPU 使用率很低,什么原因?如何排查?#

现象topload average 高达几十,但 %us%sy 都很低。

根因大量进程处于不可中断睡眠状态(D 状态),通常是因为 I/O 阻塞(磁盘/网络/外部设备)。

排查步骤

  1. topD 键排序,查看处于 D 状态的进程数量。
  2. ps aux | awk '$8=="D" {print $2,$NF}' 列出所有 D 状态进程。
  3. strace -p [PID] 看卡在哪个系统调用(通常是 read/write 磁盘或 NFS)。
  4. iostat -x 1 查看 %utilawait,若接近 100% 或 await 极高,说明磁盘 I/O 已饱和。
  5. 若磁盘正常,检查是否有 NFS 挂载超时:df -h 卡住不动说明 NFS 服务端不可达。

存储#

磁盘空间报警,但 du 统计的总大小远小于磁盘已用空间,怎么回事?#

根因文件被删除但进程仍持有句柄,空间未真正释放;或 inode 耗尽

排查步骤

  1. 先检查 inode:df -i,如果 IUse% 100%,说明小文件太多,用 find / -type f | wc -l 定位目录。
  2. 若 inode 正常,查句柄泄露:lsof +L1 列出所有已删除但未释放句柄的文件(标记为 (deleted))。
  3. 找到占用进程后:ls -l /proc/[PID]/fd/ | grep deleted 确认,重启该进程即可释放空间。
  4. 若不重启,可 echo > /proc/[PID]/fd/[fd号] 清空文件(风险操作,需确认业务影响)。

网络#

客户端无法访问服务器8080端口,怎么全链路排查?#

思路:从服务器着手,从物理层 → 网络层 → 传输层 → 应用层逐层递进。

排查步骤

  1. 服务器本机确认(物理层)netstat -tlnp | grep 8080ss -tlnp | grep 8080,确认进程是否在监听 0.0.0.0 还是 127.0.0.1(后者仅本机可访)。
  2. 服务器防火墙(网络层)iptables -L -n | grep 8080firewall-cmd --list-all,检查是否有 DROP/REJECT 规则。
  3. 连通性测试(传输层):从客户端 telnet [IP] 8080nc -zv [IP] 8080 看是否通;不通则逐跳 traceroute 看丢在哪。
  4. 抓包分析(传输层)tcpdump -i any port 8080 -nn,看三次握手是否完成(SYN→SYN+ACK→ACK)。若只有 SYN 无响应,说明服务端未回包;若回 RST,说明进程拒绝连接(可能是 backlog 满了或应用层拒绝)。
  5. 应用层curl -v [IP]:8080 看 HTTP 状态码,或查看应用日志是否有 Connection refused 异常。

无法 Ping 通目标主机/域名,如何排查?#

思路:若域名不通 IP 通,直接定位到 DNS 故障。都不通则按分层排查思路。从下往上(物理层 → 网络层 → 传输层 → 应用层),逐层缩小范围。

简洁版:先确认本地网卡和 IP 配置,再 ping 网关判断是否局域网问题;若网关通,用 traceroute 定位丢包节点,同时检查本机防火墙;若域名不通 IP 通,定位到 DNS 故障,检查 /etc/resolv.conf,ping 域名服务器确定是域名服务器不可达还是解析问题;最后,考虑到很多生产环境出于安全考虑会主动禁 ICMP 协议,我会改用 telnet 端口探测 代替 ping。

第一层:自查(排除本地低级错误/物理层)#

  1. 网络连通性:先 ping 127.0.0.1 确认本机 TCP/IP 协议栈正常;再 ping 本机 IP(非 lo)确认网卡驱动正常。
  2. 网卡状态ip aifconfig 确认网卡是否 UPRUNNING;检查网线/WiFi(物理层)。

第二层:网关与路由(局域网/网络层)#

  1. ping 网关:ping 默认网关(ip route | grep default 查),网关不通 → 问题在交换机/路由器/无线信号;网关通 → 问题在外网或目标端。
  2. traceroute 追踪
    • Linux:traceroute -n [目标IP](加 -n 跳过 DNS 解析更快)。
    • Windows:tracert -d [目标IP]
    • 看在哪一跳 超时/星号,大概率是该节点路由丢包或防火墙拦截了 ICMP 包(很多云厂商安全组默认屏蔽 ICMP)。

第三层:防火墙/安全组拦截(传输层/网络层)#

  1. 本机防火墙
    • iptables -L -n -v | grep DROP 看是否有 DROP 规则。
    • firewall-cmd --state(CentOS 7+)或 ufw status(Ubuntu)。
  2. 如果有目标主机访问权,检查:
    • 云安全组/ACL:登录云控制台,检查目标机器的 入方向安全组 是否放行了 ICMP 协议(允许 type 8 入站)。
    • 目标主机防火墙:目标主机如果开启 iptables 且 DROP 了 ICMP,本地 ping 会超时(但业务端口如 80/443 可能依然通,要区分)。

第四层:DNS 解析问题(应用层)#

现象:ping 域名不通,但 ping IP 通

  • 排查命令
    1. cat /etc/resolv.conf 检查 DNS Server 配置(如 114.114.114.114 或内网 DNS)。
    2. ping 域名服务器确定是域名服务器不可达还是解析问题
    3. 检查 /etc/hosts 是否写死了解析(被错误覆盖)。
  • 如果有装 nslookup dig 可以使用 dig @8.8.8.8dig [目标域名] 排查

第五层:目标服务存活(终极确认)#

注意:很多安全策略会 禁止 ICMP 协议(ping),但 业务端口(如 80/443)是通的

  • 此时应该用 端口探测 代替 ping:
    • telnet [目标IP] [端口]nc -zv [目标IP] [端口]
    • 如果端口通但 ping 不通 → 属于正常现象(云厂商/运维策略屏蔽 ICMP)。
    • 如果端口也不通 → 目标服务挂了,或目标主机本身无法访问。

综合#

如何查看服务/进程是否正常运行?#

原则进程在 ≠ 服务正常。 要分层判断:状态 → 进程 → 端口 → 健康探针 → 日志

  1. 托管状态:systemd 用 systemctl is-active + is-enabled,SysV 用 service xxx status
  2. 进程:没有托管就用 pgrep -af / ps -ef
  3. 端口ss -lntp 确认监听;
  4. 健康探针curl 打业务健康接口,这才是真验证;
  5. 日志journalctl -u xxx 或日志文件,看有无报错。

只做①②不算查完,必须做到④才算真健康。

参考 Shell 脚本
#!/bin/bash
# check_service.sh <name> [port] [health_url]
NAME="$1"; PORT="$2"; URL="$3"
[ -z "$NAME" ] && { echo "Usage: $0 <name> [port] [health_url]"; exit 2; }
FAIL=0
# systemd 优先
if systemctl list-unit-files 2>/dev/null | grep -q "^${NAME}\.service"; then
echo ">>> systemd unit: $NAME.service"
systemctl is-active --quiet "$NAME" \
&& echo "[OK] active" \
|| { echo "[FAIL] not active"; FAIL=1; }
systemctl is-enabled --quiet "$NAME" \
|| echo "[WARN] not enabled (won't start on boot)"
PID=$(systemctl show -p MainPID --value "$NAME")
else
echo ">>> fallback: process check"
if pgrep -f "$NAME" >/dev/null; then
PID=$(pgrep -f "$NAME" | head -1)
echo "[OK] process PID=$PID"
else
echo "[FAIL] process not found"; FAIL=1; PID=""
fi
fi
# 端口
if [ -n "$PORT" ]; then
ss -lntp 2>/dev/null | grep -q ":$PORT " \
&& echo "[OK] port $PORT listening" \
|| { echo "[FAIL] port $PORT not listening"; FAIL=1; }
fi
# 健康探针
if [ -n "$URL" ]; then
CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$URL")
[ "$CODE" = "200" ] \
&& echo "[OK] health $URL -> 200" \
|| { echo "[FAIL] health $URL -> $CODE"; FAIL=1; }
fi
[ $FAIL -eq 0 ] && echo "=== HEALTHY ===" || echo "=== UNHEALTHY ==="
exit $FAIL

恢复#

rm -rf / 误操作或误删重要文件后,怎么恢复(前提是进程未重启)?#

核心原理:Linux 中文件名和 inode 分离,文件删除只是移除目录项,只要进程还在打开该文件,数据块未被回收。

恢复步骤(假设误删 /var/log/nginx/access.log):

  1. 立即停止写入lsof | grep deleted 找到仍持有该文件句柄的进程(nginx 的 worker 进程)。
  2. 查看 fd 路径ls -l /proc/[PID]/fd/ 找到对应 fd 编号(如 4),显示为 /var/log/nginx/access.log (deleted)
  3. 重定向恢复cat /proc/[PID]/fd/4 > /var/log/nginx/access.log 将文件内容原样拷回。
  4. 安全操作:通过 kill -HUP [PID] 重新加载配置让进程重新打开新文件句柄。
  5. 注:若进程已重启,则需依赖 extundelete 或 TestDisk 等工具做文件系统级别的恢复,但成功率取决于是否立即卸载分区并停止写入。
Linux 场景题
https://blog-l7wd3.pages.dev/posts/interview/linux-scene/
作者
L7WD3-Xiao
发布于
2026-08-05
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取