如何系统性地排查服务器问题?

排查服务器问题是一个系统性工程,需要从现象诊断逐步深入到根因定位,为了帮你避开“大海捞针”的困境,我把排查过程整理成了一套标准化流程,覆盖了最常见的几个层面。

🚨 第一反应:确定问题范围

在敲命令之前,先问自己三个问题:

1、是全部服务挂了,还是某个特定应用卡了?(影响范围)

2、是突然发生的,还是最近一次变更后出现的?(变更关联:更新代码、修改配置、重启服务、网络调整等)

3、时间点: 问题是从什么时候开始的?(便于倒查日志)

🔧 核心排查路径(由外到内)

建议按以下顺序操作,每一步解决一个问题层面,不要跳过。

第1步:基础连通性 & 服务存活

ping <服务器IP>:检查网络通不通。

telnet <IP> <端口>nc -zv <IP> <端口>:检查指定端口是否开放(如 80、443、3306)。

ps aux | grep <进程名>systemctl status <服务名>:确认服务进程是否在运行。

第2步:系统资源(最常出问题的地方)

top 命令(或加强版htop)按P 键按CPU排序,按M 键按内存排序。

CPU 爆满

top -b -n 1 | grep "Cpu(s)"us(用户态)和sy(内核态)占比。

ps -eo pid,ppid,cmd,%cpu --sort=-%cpu | head:找出吃掉CPU的进程PID。

- 使用strace -p <PID> 跟踪该进程的系统调用,看它在忙什么(卡在死循环、I/O等待还是锁等待)。

内存 (RAM) 不足

free -h:看available 是否接近0,注意-/+ buffers/cache 那行才是真实可用。

topps aux --sort=-%mem 定位内存泄漏的进程。

磁盘 (Disk)

df -h:检查是否磁盘满(如//var/data),磁盘满会导致服务无法写入日志、数据库崩掉。

du -sh /| sort -rh | head -5找到哪个目录最大。

lsof | grep deleted:检查已删除但被进程占用的文件(大型日志文件常见),这些文件虽无路径但占空间。

I/O 压力 (I/O Wait)

iostat -x 2 5:看%iowait 是否过高,重点关注await(平均等待时间,单位ms,大于100ms说明磁盘很慢)和%util(磁盘繁忙度)。

iotop:直接看到哪个进程在读写磁盘。

dmesg | tail -20:看是否有I/O errorbad sector 等磁盘坏道信息。

第3步:应用程序日志(最重要的一步)

无论资源多紧张,最终还是看应用报了什么错。

journalctl -u <服务名> -f:对于systemd管理的服务,实时查看日志。

tail -200f /var/log/nginx/access.log/var/log/messages

grep -i "error" /var/log/app.log | tail -50:直接搜 Error。

fail2ban 日志:如果是被暴力破解或防火墙误封。

关键点:时间戳要对准,如果日志出现大量OutOfMemoryErrorConnection RefusedNo space left on device,90%的问题能在这里找到线索。

第4步:网络排查

ss -tlnpnetstat -tlnp:查看所有监听端口,看看实际监听的是不是你以为的端口(Nginx 监听了 80,但实际有个程序占用了)。

ss -tan | grep :<端口>:查看该端口的连接数,关注TIME_WAITSYN_RECV 状态。

ping <目标域名>nslookup <目标域名>:检查 DNS 解析是否正常。

curl -v -I localhost:<端口>:从服务器内部请求自己,看是否正常,正常的话再curl -v -I 外网IP,对比差异。

tcpdump -i eth0 port <端口> -c 100:抓包分析,看是否有大量重传或RST包(网络拥塞或防火墙丢包)。

mtr <目标IP>:持续跟踪路由,看哪一跳出现高延迟或丢包。

第5步:数据库与中间件

慢查询mysqldumpslow -t 10 /var/lib/mysql/slow.logpg_stat_statements

连接池SHOW PROCESSLIST; 看是否有大量SleepLocked 状态。

缓存(Redis)redis-cli info stats | grep rejected_connectionsMONITOR 看是否有命令堵塞。

消息队列(RabbitMQ/Kafka):看连接数、消费者消费速度、unacked 消息积压。

🔍 杀手锏工具

当常规思路无效时,试试这些:

strace -p <PID>:跟踪进程系统调用,如果看到大量futex(0x..., FUTEX_WAIT),说明在等待锁(可能是死锁或锁竞争),如果看到write() 一直卡住,可能是磁盘I/O。

perf top:实时查看CPU热点函数,定位到底是哪个C函数或内核调用在消耗CPU。

perf record -a -g -s +perf report:做CPU采样,生成火焰图。

vmstat 1 10:查看上下文切换(cs 列)、CPU等待队列(r 列)、CPU用户态/内核态占比。

dmesg -T:看内核日志,尤其关注Out of memory: Kill process...(OOM killer 杀进程)或kernel BUG at(内核错误)。

💡 快速排查清单(按可能性排序)

场景 最可能原因 查什么
网站/API 502/504 Nginx 连不上后端ss -tlnp 检查后端端口,curl 本地后端
服务启动立即挂掉 配置错误、端口冲突、依赖服务没起来systemctl status 看退出code,journalctl -xe 看具体报错
响应很慢 数据库慢查询、Redis 缓存失效、磁盘I/O高iostattopmysql slow log
偶尔超时/卡顿 网络丢包、JVM Full GC、数据库锁ping -fvmstatjstat -gc
CPU 飙高 应用死循环、大量请求、内核bugtopstraceperf
磁盘空间报警 日志文件过大、数据库 binlog、docker overlaydf -hdu -shlsof

🧠 终极心法:假设驱动法

如果上述都试了还不行,别慌,大胆提出一个可复现的假设

假设1:是网络问题? -> 换台机器测试,请求不同的端口。

假设2:是硬件问题? -> 检查dmesg 中的硬件错误,查ipmitool sensor 看温度。

假设3:是负载均衡/防火墙策略问题? -> 跳过负载转发,直连源站测试。

每次只改一个变量,观察结果。 记录你改了什么、看到了什么。

1、ping +top:确认机器活着且资源没耗尽。

2、journalctl -xetail -200 /var/log/nginx/error.log:看应用层报错。

3、df -h:确认磁盘没满。

4、ss -tlnp:确认端口监听正确。

5、strace -p <主PID>:看进程在干什么。

6、dmesg -T:看内核有没有杀进程或爆内存。

按照这个路径走,95%以上的服务器问题都能在10分钟内定位到根因,如果还不行,把过程中的关键输出写成清晰的问题描述 + 时间点 + 错误日志片段,在提问时附上,能帮你更快获得有效帮助。

文章摘自:https://idc.huochengrm.cn/fwq/25065.html

评论