news 2026/10/14 7:27:50

Linux线上问题排查实战:系统资源、进程线程、网络连接与日志分析命令体系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux线上问题排查实战:系统资源、进程线程、网络连接与日志分析命令体系

1. 线上问题排查的核心思路与命令体系拆解

线上出问题的时候,最怕的不是问题本身有多复杂,而是手忙脚乱不知道从哪里下手。我经历过好几次半夜被叫起来处理故障的场景,最开始那几次真的是两眼一抹黑,登录到机器上到处乱敲,结果越搞越乱。后来踩坑踩多了,慢慢总结出一套自己的排查路径和常用命令组合,基本上能在几分钟内定位到大致方向。

这套东西说白了就一句话:先看全局,再钻细节,从外到内逐层收敛。听起来像废话,但真正在紧张的环境下能按这个节奏走的人不多。大多数人一上来就盯着某个自己怀疑的点猛查,结果方向错了,白白浪费时间。

这篇文章适合谁看?如果你是刚接触线上运维或者后端开发的,还没形成自己的排查套路,那这些内容可以直接拿去用。如果你已经有一定经验,也可以看看我在每个环节用的具体命令和参数,说不定有你没注意到的细节。我尽量把每个命令为什么这么用、什么场景下用、输出怎么看都讲清楚,不堆砌命令列表,而是按排查流程串起来。

整个排查体系我分成四个层面:系统资源层、进程与线程层、网络连接层、应用日志层。这四个层面基本覆盖了绝大多数线上问题的排查需求。下面逐个展开,把每个层面常用的命令、参数、输出解读和实操经验都过一遍。

2. 系统资源层:CPU、内存、磁盘、负载的快速体检

2.1 用 top 和 uptime 建立第一印象

登录到出问题的机器上,我第一个敲的命令永远是uptime。这个命令输出极简,但信息量很大:

uptime # 输出示例: 14:32:05 up 127 days, 3:22, 4 users, load average: 8.52, 6.31, 4.97

重点看load average后面三个数,分别代表1分钟、5分钟、15分钟的平均负载。怎么判断高不高?用负载值除以CPU核心数。比如这台机器是4核,1分钟负载8.52,那就是8.52/4≈2.13,意味着平均每个核心上有2.13个任务在排队,已经明显过载了。

更关键的是看趋势:如果1分钟值远高于15分钟值(比如8.52 vs 4.97),说明负载在快速上升,问题正在恶化;反过来如果1分钟值在下降,说明高峰可能已经过去了。这个趋势判断在决定要不要紧急扩容时特别重要。

紧接着就是top,这个大家都会用,但我重点说几个容易被忽略的操作:

  • 按1可以展开看每个CPU核心的使用率,能快速判断是单核跑满还是多核均衡
  • 按Shift+M按内存排序,Shift+P按CPU排序,Shift+T按运行时间排序
  • top -H -p <pid>可以看某个进程下所有线程的资源占用,排查多线程问题时必用

注意:top 默认3秒刷新一次,在排查快速变化的问题时可以按d然后输入1改成1秒刷新,但别改太快,否则输出刷屏根本看不清。

2.2 内存排查:free、vmstat 和 OOM 的蛛丝马迹

内存问题最隐蔽,因为它不像CPU那样直接体现为响应变慢,很多时候是突然进程被杀或者服务崩溃。free -h是最常用的:

free -h # total used free shared buff/cache available # Mem: 31Gi 28Gi 1.2Gi 512Mi 1.8Gi 1.5Gi

这里最容易看错的是free那一列。Linux会把大量空闲内存拿去做缓存(buff/cache),所以free很小不代表内存不够。真正要看的是available这一列,它才是应用程序真正可以用的内存量。上面这个例子 available 只有1.5Gi,说明内存确实紧张了。

如果怀疑有进程被OOM Killer干掉了,用dmesg查:

dmesg -T | grep -i "oom\|killed process"

这个命令能直接告诉你哪个进程在什么时间被系统杀掉了,以及当时的内存状况。我遇到过好几次服务莫名其妙重启,最后都是通过这个命令确认是内存泄漏导致被OOM。

vmstat 1也是内存排查利器,重点看si和so两列(swap in/out)。如果这两个值持续不为0,说明系统在频繁使用交换分区,性能会急剧下降。正常情况这两个值应该一直是0。

2.3 磁盘与IO:df、iostat 和 du 的组合拳

磁盘满了是线上最常见的问题之一,df -h一眼就能看出来:

df -h # Filesystem Size Used Avail Use% Mounted on # /dev/vda1 99G 94G 1.2G 99% /

Use% 超过90%就要警惕了,超过95%基本就要立即处理。但光看 df 不够,还得知道是什么占满了。我常用的组合是:

# 从根目录逐层往下找大目录 du -h --max-depth=1 / 2>/dev/null | sort -rh | head -20

这个命令会列出根目录下每个一级目录的大小并降序排列,然后你对着最大的那个目录再执行一次,逐层定位到具体的大文件。这个过程听起来笨,但比任何工具都可靠。

如果磁盘没满但IO很高,用iostat -x 1看:

iostat -x 1 # Device r/s w/s rkB/s wkB/s await %util # vda 120.5 340.2 4820 13608 15.3 98.7

重点看%util,接近100%说明磁盘IO已经饱和。await是平均等待时间(毫秒),正常应该在个位数,超过20就要关注了。如果%util高但r/s和w/s都不大,可能是磁盘硬件本身有问题。

实操心得:有一次线上数据库响应极慢,CPU和内存都正常,最后用 iostat 发现 %util 持续100%,但读写次数很低,换了一块盘就好了。硬件故障有时候比软件问题更隐蔽。

3. 进程与线程层:定位资源消耗的元凶

3.1 ps 命令的高阶用法

ps大家都会用,但很多人只用ps aux | grep xxx。其实排查线上问题时,几个组合用法效率更高:

# 按CPU使用率降序排列,取前10 ps aux --sort=-%cpu | head -11 # 按内存使用率降序排列 ps aux --sort=-%mem | head -11 # 查看进程的启动时间和运行时长 ps -eo pid,lstart,etime,cmd | grep <进程名>

etime显示进程已经运行了多久,如果发现某个进程刚启动不久,结合服务日志就能判断是不是刚重启过。lstart显示精确的启动时间,在排查“服务什么时候挂的”这类问题时特别有用。

还有一个很实用的技巧:查看进程的父子关系树。

ps -ef --forest | grep -A 5 <进程名>

这个能帮你理清进程之间的调用关系,尤其是排查脚本启动的服务时,能快速找到真正的父进程。

3.2 线程级排查:top -H 和 jstack 配合

当发现某个Java进程CPU很高时,光看进程级别不够,得钻到线程级别:

# 第一步:找到CPU最高的进程 top -c # 假设PID是12345 # 第二步:查看该进程下所有线程的CPU占用 top -H -p 12345 # 第三步:找到CPU最高的线程,假设TID是12378 # 把线程ID转成16进制 printf "%x\n" 12378 # 输出:305a # 第四步:用jstack导出线程栈,搜索这个16进制ID jstack 12345 | grep -A 30 "305a"

这一套组合拳下来,基本能定位到具体是哪段代码在消耗CPU。我排查过好几次死循环导致的CPU飙高,都是靠这个方法找到的。

对于非Java的应用,可以用gdb或者perf来分析,但原理是一样的:先找到线程,再看线程在干什么。

3.3 文件句柄与进程限制

有时候服务报“Too many open files”,问题出在文件句柄数上:

# 查看系统级限制 cat /proc/sys/fs/file-max # 查看进程级限制 cat /proc/<pid>/limits | grep "open files" # 查看当前进程已打开的文件句柄数 ls /proc/<pid>/fd | wc -l # 查看具体打开了哪些文件 ls -l /proc/<pid>/fd | head -20

如果发现句柄数接近限制值,要么调大限制(修改/etc/security/limits.conf),要么排查是不是有句柄泄漏。句柄泄漏通常是因为打开了文件或网络连接没有正确关闭,用lsof -p <pid>可以看到具体的连接状态。

注意:修改 limits.conf 后需要重新登录或者重启服务才能生效,别改完就以为好了。

4. 网络连接层:从连通性到连接状态的全面诊断

4.1 连通性排查:ping、telnet 和 curl 的正确打开方式

网络问题排查的第一步永远是确认连通性。但很多人只会ping,其实不同场景要用不同工具:

# 基础连通性 ping -c 4 <目标IP> # 检查特定端口是否可达 telnet <目标IP> <端口> # 或者用 nc nc -zv <目标IP> <端口> # 检查HTTP服务是否正常 curl -v -o /dev/null -s -w "HTTP状态码: %{http_code}\n连接时间: %{time_connect}s\n总时间: %{time_total}s\n" http://<目标地址>

curl的-w参数特别有用,可以输出详细的耗时分解。time_connect是TCP连接建立的时间,time_total是完整请求的时间。如果time_connect很长,说明网络延迟高或者对方响应慢;如果time_connect正常但time_total很长,说明是服务处理慢。

4.2 连接状态分析:ss 和 netstat 的实战对比

netstat是老牌命令,但现在更推荐用ss,因为它更快且信息更全:

# 查看所有TCP连接状态统计 ss -s # 查看特定端口的连接 ss -tnp | grep :8080 # 统计各状态的连接数 ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn

重点关注的连接状态:

状态含义异常判断
ESTABLISHED已建立的连接数量突增可能是流量暴涨或连接泄漏
TIME_WAIT等待关闭的连接大量出现说明短连接频繁,考虑连接池
CLOSE_WAIT等待应用关闭持续增多说明应用没有正确关闭连接
SYN_RECV收到SYN但未完成握手大量出现可能是SYN Flood攻击

CLOSE_WAIT 是我遇到最多的问题。如果这个状态的连接数持续增长,基本可以确定是应用程序的bug——收到了对方的FIN但没有调用close()关闭连接。这种情况光靠调系统参数没用,必须改代码。

TIME_WAIT 过多则是另一个极端,通常是短连接太多。解决办法是使用连接池,或者调整内核参数:

# 查看当前TIME_WAIT相关参数 sysctl net.ipv4.tcp_tw_reuse sysctl net.ipv4.tcp_max_tw_buckets

实操心得:tcp_tw_reuse 可以安全开启,它允许将TIME_WAIT状态的连接重新用于新的TCP连接。但 tcp_tw_recycle 在NAT环境下会导致问题,新版本内核已经移除了这个参数,不建议使用。

4.3 抓包分析:tcpdump 的精准用法

当连通性和连接状态都正常但服务就是不通时,就得上抓包了:

# 抓取指定网卡、指定端口、指定IP的包 tcpdump -i eth0 -nn port 8080 and host 192.168.1.100 -w /tmp/capture.pcap # 实时查看HTTP请求 tcpdump -i eth0 -nn -A port 80 | grep -E "GET|POST|HTTP" # 抓取特定数量的包后自动停止 tcpdump -i eth0 -nn -c 100 port 443

抓包文件可以用tcpdump -r读取,也可以下载到本地用Wireshark分析。我一般会先抓100个包看看有没有明显的异常,比如TCP重传、RST包等。

# 检查是否有TCP重传 tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'

这个命令专门抓RST包,如果频繁出现RST,说明连接被异常重置,可能是防火墙拦截或者服务端主动拒绝。

5. 应用日志层:从日志中快速提取关键信息

5.1 日志查看的基本功

日志排查的核心就三个操作:找、筛、追。

# 实时追踪日志 tail -f /var/log/app/application.log # 查看最后100行 tail -n 100 /var/log/app/application.log # 搜索关键字 grep "ERROR" /var/log/app/application.log # 搜索并显示上下文 grep -C 5 "Exception" /var/log/app/application.log # 统计错误出现次数 grep -c "ERROR" /var/log/app/application.log

grep -C 5这个参数特别重要,它显示匹配行的前后5行,能帮你看到异常发生时的上下文。很多时候错误信息本身不够,需要看前面的调用链和后面的堆栈。

5.2 大日志文件的处理技巧

线上日志动辄几个G,直接cat或者grep会非常慢。几个提速技巧:

# 用tail查看文件末尾,比cat快得多 tail -n 10000 application.log | grep "ERROR" # 用sed查看指定时间范围的日志 sed -n '/2024-01-15 14:00:00/,/2024-01-15 14:05:00/p' application.log # 用awk做更复杂的过滤 awk '/2024-01-15 14:00/,/2024-01-15 14:05/' application.log | grep "ERROR" # 统计每分钟的日志量 awk '{print substr($2,1,5)}' application.log | uniq -c

最后一个命令特别有用,能快速看出哪个时间段日志量突增,通常对应着问题发生的时间点。

5.3 日志中的关键信号

看日志不能只看ERROR,有些信号藏在WARN和INFO里:

  • 频繁的GC日志:说明内存压力大,可能需要调整堆大小
  • 连接池等待:说明连接池配置不够,需要调大
  • 重试日志:说明下游服务不稳定
  • 超时日志:说明网络或者下游处理慢

我一般会先用grep -c统计各类日志的数量,找出异常多的那一类,再深入看具体内容。这个方法比从头翻日志快得多。

注意:有些日志框架会异步写日志,服务崩溃时最后几条日志可能丢失。如果发现日志突然中断,不要以为服务是正常停止的,很可能是崩溃了。

6. 常见问题速查与排查路径总结

6.1 典型问题排查路径速查表

问题现象第一步第二步第三步
服务响应慢uptime看负载top看CPU/内存iostat看磁盘IO
服务无响应ss看连接状态检查CLOSE_WAITjstack看线程栈
服务频繁重启dmesg看OOM检查内存泄漏看启动日志
网络不通ping测连通telnet测端口tcpdump抓包
磁盘告警df -h看使用率du逐层定位清理或扩容
CPU飙高top -H看线程jstack定位代码分析死循环

6.2 我踩过的几个坑

第一个坑:只看平均值不看分布。有一次CPU使用率显示只有60%,看起来不高,但服务就是慢。后来用mpstat -P ALL 1发现是单核跑满,其他核空闲。原因是应用没有做好多核并行,所有请求都压在一个核上。所以看CPU一定要用top按1展开看每个核的情况。

第二个坑:忽略TIME_WAIT的影响。有一次压测时QPS上不去,查了半天发现是TIME_WAIT连接太多导致端口耗尽。后来开启了tcp_tw_reuse并调整了端口范围才解决。这个问题的隐蔽性在于,它不会导致报错,只是性能上不去。

第三个坑:日志级别设置不当。生产环境开了DEBUG级别日志,结果磁盘IO被日志写满,影响了正常业务。后来改成INFO级别,并且对日志做了异步和限流处理。这个教训告诉我,日志虽好,但不能贪多。

第四个坑:排查时改了配置忘了改回来。有一次为了排查问题临时调大了某个参数,问题解决后忘了恢复,结果过了一段时间引发了另一个问题。现在我养成了习惯,所有临时改动都记在备忘录里,排查结束后逐一确认恢复。

6.3 建立自己的排查清单

最后分享一个我自己的做法:把常用的排查命令整理成一个脚本,登录机器后直接跑一遍,输出一份系统体检报告。这样即使半夜被叫起来脑子不清醒,也能按部就班地收集信息。

#!/bin/bash echo "===== 系统负载 =====" uptime echo "===== CPU TOP5 =====" ps aux --sort=-%cpu | head -6 echo "===== 内存 TOP5 =====" ps aux --sort=-%mem | head -6 echo "===== 磁盘使用 =====" df -h | grep -v tmpfs echo "===== 连接状态统计 =====" ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn echo "===== 最近OOM记录 =====" dmesg -T | grep -i "oom\|killed" | tail -5

这个脚本跑一遍大概10秒钟,但能覆盖80%的常见问题。我把它放在每台服务器的/usr/local/bin/下,需要的时候直接执行,省去了逐个敲命令的时间。

排查线上问题这件事,工具和命令只是基础,更重要的是形成自己的排查思路和节奏。遇到问题不要慌,按照“系统资源→进程线程→网络连接→应用日志”这个顺序逐层排查,大部分问题都能在几分钟内定位到方向。剩下的就是经验和细节的积累了,踩的坑越多,下次排查就越快。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 7:27:20

Oracle 11.2.0.4 PSU补丁实战:从应用到回滚全流程解析

简介&#xff1a;面向Oracle数据库11.2.0.4版本的周期补丁集更新PSU&#xff08;编号p33477185&#xff0c;2022年1月发布&#xff09;专为Linux x86-64平台设计&#xff0c;属于官方安全与性能维护更新&#xff0c;主要用于修复安全漏洞、消除已知问题并提升数据库运行稳定性&…

作者头像 李华
网站建设 2026/10/14 7:26:54

计算机网络复试高频考点:故障驱动型小题精讲

1. 项目概述&#xff1a;为什么一份“小题总结”值得花三天重写三遍“西电复试计算机网络 小题总结”——这八个字背后&#xff0c;不是一份简单的考前笔记&#xff0c;而是一套被某高校通信工程方向复试现场反复验证过的知识压缩-错误拦截-临场调用三重机制。我连续三年参与该…

作者头像 李华
网站建设 2026/10/14 7:26:50

具身智能的终点不是人形,实时音视频才是神经系统

2025年开年&#xff0c;人形机器人跳舞、跑步、做家务的视频刷遍全网&#xff0c;看着它们越来越像人的动作&#xff0c;很多朋友都在问同一个问题&#xff1a;人形机器人是不是具身智能的终点&#xff1f;我的回答可能和主流叙事不太一样&#xff1a;具身智能的终点从来不是“…

作者头像 李华
网站建设 2026/10/14 7:26:38

PS5远程串流全指南:从主机设置到网络优化,随时随地玩遍游戏

串流游戏这个东西&#xff0c;我前前后后折腾了小半年&#xff0c;踩过的坑能写满一页纸&#xff0c;但带来的便利也是实打实的。所谓“AnyPS5”&#xff0c;我自己的理解很简单&#xff1a;不管手里是手机、平板、轻薄本还是办公室的电脑&#xff0c;只要能装客户端、能联网&a…

作者头像 李华
网站建设 2026/10/14 7:26:30

Windows系统安装生存指南:硬件兼容、分区策略与驱动优化

1. 这不是重装系统教程&#xff0c;而是一份给真实用户的“系统安装生存指南”你是不是也经历过&#xff1a;硬盘突然变砖、蓝屏代码看都看不懂、重装完发现驱动全丢、连WiFi都连不上&#xff1f;我做过上百次Windows系统安装&#xff0c;从XP时代用光盘启动&#xff0c;到如今…

作者头像 李华
网站建设 2026/10/14 7:26:19

Python表单接口开发实战:分层设计与MCP工具化

1. 从表单到接口&#xff1a;为什么这套开发路径值得花时间啃表单系统在业务系统里属于那种“看起来简单、做起来全是坑”的模块。很多人第一次接触表单接口开发&#xff0c;觉得无非就是增删改查&#xff0c;几张表、几个字段、一套RESTful路由就完事了。但真正落到实际项目里…

作者头像 李华