13 10 月 2026

服务器突然卡死、网站打不开、游戏服掉线,八成是资源到瓶颈了。但"卡"只是表象,得知道是 CPU、内存、磁盘还是带宽的问题。

这篇给你一套按顺序执行就能定位问题的排查流程,以及每种瓶颈的处理办法。

资源不够用通常就两条路:优化或升级。财富云计算 的云服务器支持弹性升级;做内网服务、游戏服务端可选 NAT 型(无独立公网 IP,价格比独立 IP 机型省一半以上)。

一、30 秒快速体检

连上服务器先跑这四条:

uptime        # 看负载
free -h       # 看内存
df -h         # 看磁盘
top           # 看谁在吃资源(按 q 退出)

1)uptime —— 负载

$ uptime
 14:32:01 up 30 days,  4:12,  2 users,  load average: 4.52, 3.81, 2.90

三个数字是 1 分钟、5 分钟、15 分钟的平均负载。

怎么判断高不高:看 CPU 核数(nproc)。

  • 4 核机器,负载 4.0 左右 = 刚好跑满
  • 4 核机器,负载 8.0 = 有一半进程在排队等 CPU,明显过载
  • 1 分钟值远高于 15 分钟值 = 突发高峰;反过来说明高峰正在缓解
负载高 ≠ CPU 高。负载包含"等待 IO 的进程"(比如磁盘卡死、数据库锁表也会让负载飙升),所以要配合 top 看 %wa。

2)free -h —— 内存

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           7.7G        5.2G        412M        128M        2.1G        2.0G
Swap:          2.0G        512M        1.5G

重点看 available(真正还能用的),不是 free。Linux 会拿空闲内存做缓存(buff/cache),所以 free 小是正常的,buff/cache 大反而是好事。

危险信号:

  • available 接近 0 → 内存快耗尽
  • Swap 被大量使用 → 已经在用磁盘当内存,会非常慢

3)df -h —— 磁盘

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        50G   47G  1.2G  98% /

Use% 超过 85% 就要处理了,到 100% 会导致数据库写不进去、服务崩溃、连 SSH 都可能异常。

4)top —— 进程

top - 14:32:01 up 30 days,  4:12,  2 users,  load average: 4.52, 3.81, 2.90
Tasks: 180 total,   1 running, 179 sleeping,   0 stopped,   0 zombie
%Cpu(s): 45.2 us,  8.3 sy,  0.0 ni, 40.1 id,  6.2 wa,  0.0 hi,  0.2 si,  0.0 st
MiB Mem :   7900.0 total,    412.0 free,   5300.0 used,   2188.0 buff/cache
MiB Swap:   2048.0 total,   1536.0 free,    512.0 used

CPU 行各项含义:

字段含义高说明什么
us用户进程占用业务程序本身耗 CPU,正常
sy内核占用系统调用频繁(可能是大量小 IO、网络包)
ni调整过优先级的进程有 nice 过的任务
id空闲越低越忙
wa等待 IO磁盘慢!数据库慢!这是关键指标
hi/si硬中断/软中断网络包风暴或硬件问题
st被宿主机偷走的 CPU虚拟化超卖,云主机要关注

st 高(比如 >5%)说明同宿主上的邻居抢资源,这是云服务器的"共享型"常见的坑,联系服务商或换独享型。

top 里的实用快捷键:

P    按 CPU 排序(默认)
M    按内存排序
N    按 PID 排序
1    展开显示每个 CPU 核心
c    显示完整命令行(看进程具体跑的什么)
k    杀进程(输入 PID)
u    只看某个用户的进程

二、CPU 高的排查

定位哪个进程

top -c                       # 按 P 排序,看 COMMAND 列
ps aux --sort=-%cpu | head -10

进一步:进程里哪个线程在烧 CPU

top -H -p <PID>              # 显示该进程的所有线程
# 找到线程 TID 后转 16 进制
printf "%x\n" <TID>
# 如果是 Java 程序,用 jstack 定位
jstack <PID> | grep -A 20 <16进制TID>

常见原因与处理

原因判断依据处理
业务量真的大us 高且持续升级配置 / 加机器做负载
死循环 / 程序 bug某个进程常年 100%重启该进程、查日志、修 bug
挖矿木马陌生进程名、minerd/kworker 异常立即排查入侵,见《服务器被入侵应急排查》
日志级别开太高sy 也高,磁盘在疯狂写调低日志级别
编译/解压等正当任务自己发起的等它跑完,或用 nice 降优先级
st 高虚拟化超卖换机型/服务商

临时救急:降低某进程优先级,别让它拖垮整机

renice +19 -p <PID>
# 或者启动时就限制
nice -n 19 ./heavy_task.sh

长期限制:用 systemd 的 CPUQuota(见《systemd 服务编写与开机自启实战》)

[Service]
CPUQuota=150%      # 最多用 1.5 个核

三、内存不足的排查

定位占内存的进程

ps aux --sort=-%mem | head -10
# 或者 top 后按 M

看更细的内存分布

cat /proc/meminfo
# 关注:
# MemAvailable
# Slab(内核对象缓存)
# HugePages

# slab 占用异常(常见于大量小文件/连接)
slabtop

排查内存泄漏

# 监控某个进程的内存变化
watch -n 5 'ps -o pid,rss,vsz,cmd -p <PID>'

# 看系统整体趋势
sar -r 1 10

RSS 只增不减且不停上涨 = 内存泄漏,只能重启进程 + 修程序。

缓存占用能不能手动释放

# 只是一次性释放 buff/cache(一般不必做)
sync && echo 3 > /proc/sys/vm/drop_caches
注意:这是"释放缓存",不是"解决内存不足"。缓存是拿来提升性能的,清掉后下次读文件还要重新加载。真正内存不足要查进程。

OOM(内存耗尽杀进程)

dmesg | grep -i "out of memory"
grep -i "killed process" /var/log/syslog
journalctl -k | grep -i oom

看到类似 Killed process 1234 (mysqld) 就是内核把占内存最大的杀了。

处理思路:

  1. 给关键服务加 systemd 的 MemoryMax,先保住系统不被拖死
  2. 调低程序配置(如 MySQL 的 innodb_buffer_pool_size、Java 的 -Xmx、游戏服的地图/人数)
  3. 加 swap 应急:
# 创建 2G swap 文件
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

# 调整使用倾向(1-100,越小越不用 swap)
sysctl vm.swappiness=10
echo 'vm.swappiness=10' >> /etc/sysctl.conf
  1. 实在不够就升级内存

四、磁盘满了的排查

先确认是不是真满

df -h              # 看分区使用率
df -i              # ⚠️ 看 inode 使用率(也可能是 inode 耗尽)

inode 耗尽的表现:磁盘还有空间,但写不进新文件,df -h 正常却报 No space left on device。常因海量小文件(如缓存碎片、session 文件)。

找大文件和大目录

# 逐层看目录大小
du -sh /*  2>/dev/null | sort -h
du -sh /var/* | sort -h
du -sh /var/log/* | sort -h

# 只找超过 500M 的文件
find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -k5 -h

# 找最近 7 天改过的大文件
find / -type f -size +100M -mtime -7 2>/dev/null

推荐装 ncdu(交互式分析,比 du 直观得多):

apt install ncdu -y
ncdu /

常见"磁盘杀手"

元凶路径清理
系统日志/var/log/journalctl --vacuum-size=200M,删 .gz 旧日志
Nginx/Apache 日志/var/log/nginx/配 logrotate,或 truncate
Docker 数据/var/lib/docker/docker system prune -a
包缓存/var/cache/apt/archives/apt clean
数据库 binlog/var/lib/mysql/过期 binlog 清理,设 expire_logs_days
备份文件/backup/ 等定期清理旧备份
core dump/var/lib/systemd/coredump/rm -f /var/lib/systemd/coredump/*
网站上传/临时文件/tmp清理 /tmp 下旧文件
已删除但仍被占用的文件—见下方

特殊坑:文件删了但空间没释放

# 找出已被删除但仍被进程占用的文件
lsof | grep deleted
# 或
lsof +L1

表现:df 显示满了,但 du 加起来对不上。原因是某进程(常是被重启过的服务、或忘了轮转的日志)还持有已删除文件的句柄。

解决:重启持有它的进程,或在线截断:

# 在线清空大日志而不删文件(不影响正在写日志的进程)
: > /var/log/nginx/access.log
# 或者
truncate -s 0 /var/log/huge.log

磁盘 IO 慢(不是满,是慢)

iostat -x 1          # 需 apt install sysstat
iotop                # 看谁是 IO 大户(需 apt install iotop)

看 %util(接近 100% 说明磁盘打满)和 await(响应毫秒数,>20ms 就偏慢)。


五、带宽和网络排查

看实时流量

apt install iftop nethogs -y
iftop -i eth0                    # 看连接级别的流量
nethogs eth0                     # 看进程级别的流量
sar -n DEV 1                     # 看网卡吞吐

看连接数

ss -s                            # 总连接数统计
ss -ant | awk '{print $1}' | sort | uniq -c    # 各状态连接数
netstat -n | grep :80 | wc -l

异常信号:

  • TIME_WAIT 巨多 → 短连接过多,考虑开启 keepalive 或复用
  • SYN_RECV 巨多 → 可能被 SYN Flood,检查是否被攻击
  • ESTABLISHED 来自少量 IP 且数量巨大 → 可能是 CC 攻击

排查带宽跑满

# 看哪个 IP 流量最大
iftop -i eth0 -n

# 统计访问最多的 IP(Web 场景)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20

处理:

  • 真有量大:升级带宽
  • 被盗链/被采集:加 Referer 校验、限速、封 IP
  • 被攻击:见《网站被 CC 攻击怎么办》

网络质量测试

ping -c 10 目标IP                 # 丢包率、延迟
mtr 目标IP                        # 逐跳定位哪一跳出问题(比 traceroute 好)
curl -o /dev/null -s -w "%{speed_download}\n" https://example.com/file

六、一键体检脚本

把下面存成 /usr/local/bin/check.sh,出问题直接跑:

#!/bin/bash
echo "===== 系统 ====="
uptime
echo
echo "===== CPU 核数 ====="
nproc
echo
echo "===== 内存 (MB) ====="
free -m
echo
echo "===== 磁盘 ====="
df -h | grep -v tmpfs
echo
echo "===== inode ====="
df -i | grep -v tmpfs
echo
echo "===== CPU Top5 ====="
ps aux --sort=-%cpu | head -6
echo
echo "===== 内存 Top5 ====="
ps aux --sort=-%mem | head -6
echo
echo "===== 负载与IO ====="
top -bn1 | head -3
echo
echo "===== 监听端口 ====="
ss -tulnp | head -20
echo
echo "===== 失败的服务 ====="
systemctl --failed
echo
echo "===== 最近错误日志 ====="
journalctl -p err -n 20 --no-pager
chmod +x /usr/local/bin/check.sh
check.sh

七、长期监控:别等出问题才知道

最小方案:crontab 定时采集,超阈值发告警。

# 每 5 分钟检查一次磁盘,超过 85% 就写日志
*/5 * * * * df -h | awk '$5+0 > 85 {print $0}' >> /var/log/disk-alert.log

推荐方案:装个轻量监控。

  • Netdata:一行命令装好,自带 Web 面板,实时看所有指标

    bash <(curl -Ss https://my-netdata.io/kickstart.sh)
    # 访问 http://你的IP:19999
  • Prometheus + Grafana:专业方案,适合多台机器
  • 云厂商自带的监控:控制台直接看曲线 + 配告警

本站《游戏服务器监控与告警实战》有更完整的搭建教程。


八、排查流程总结(照着走)

服务器卡 / 服务异常
   │
   ├─ uptime 看负载
   │     └─ 负载高 → top 看 %wa
   │           ├─ wa 高 → 磁盘 IO 问题 → iostat / iotop
   │           ├─ us 高 → 业务进程 → ps aux --sort=-%cpu
   │           └─ st 高 → 宿主机超卖 → 换机型
   │
   ├─ free -h 看内存
   │     └─ available 低 → ps aux --sort=-%mem → 泄漏?配置过大?→ 限流/加swap/升级
   │
   ├─ df -h + df -i 看磁盘
   │     └─ 满 → ncdu / du -sh 找大文件 → 日志?备份?→ 清理 + logrotate
   │            └─ 对不上 → lsof | grep deleted
   │
   ├─ iftop 看带宽
   │     └─ 满 → 查访问来源 → 盗链/攻击/真流量大
   │
   └─ 都正常 → 查应用日志
         journalctl -u 服务名 -n 100
         tail -f /var/log/nginx/error.log

如果排查下来确认是配置不够,就该升级了。财富云计算 的云服务器支持按需升级 CPU、内存、带宽;做游戏服务端、内网服务也可以先试 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上),把省下来的预算放到内存和 CPU 上更划算。

相关阅读:

  • 《systemd 服务编写与开机自启实战》
  • 《Linux 常用命令速查表》
  • 《服务器备份与快照策略》
延伸阅读
  1. 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
  2. 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
  3. 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
  4. 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
  5. 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
  6. RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
  7. 短链接服务搭建:Shlink 自托管,链接数据自己掌握
  8. 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道
更多阅读
  1. 上一篇:Linux 文件权限与用户组详解:chmod / chown 到底该怎么设
  2. 下一篇:服务器备份与快照策略:数据没了才想起备份就晚了
发表评论 9