4、进程管理与系统监控:从查看到调优,把脉你的服务器
进程管理,说白了就是跟操作系统里的“活人”打交道。每个程序跑起来就是一个进程,它们抢CPU、占内存、争IO,乱成一锅粥的时候,你就得站出来当那个“交警”。
我刚开始做运维那会儿,最怕的就是线上服务突然变慢。老板站背后问“咋回事”,我对着黑乎乎的终端只能瞎猜。后来才明白,不是工具不好使,是我没用好。今天咱们就把这些看家本事捋一遍。
核心思路:先看整体负载(uptime),再查进程详情(ps/top),最后定位瓶颈(vmstat/iostat)。别一上来就翻日志,那是最后一步。
4.1 进程查看:你得知道谁在干活
4.1.1 ps:静态快照,一锤子买卖
ps 命令就像拍照片,你按下快门那一瞬间,进程是什么样就是什么样。我个人习惯用 ps aux,这个组合能看全所有用户的进程,而且输出格式比较友好。
# 查看所有进程,带完整命令行
ps aux
# 只看某个进程,比如 nginx
ps aux | grep nginx
# 想看进程树,父子关系一目了然
ps axjf
输出里有个 STAT 列,我重点说一下:
| 状态码 | 含义 | 常见场景 |
|---|---|---|
| R | Running / Runnable | 正在跑或排队等CPU |
| S | Sleeping(可中断) | 等IO完成,比如读磁盘 |
| D | Uninterruptible Sleep | 等磁盘IO,kill -9都杀不掉 |
| Z | Zombie(僵尸) | 子进程死了,父进程没收尸 |
| T | Stopped | 被暂停了,比如按了Ctrl+Z |
一个小技巧:看到大量 D 状态进程,别急着 kill,先检查磁盘是不是挂了。我曾经在 NFS 挂载点出问题时,满屏都是 D 状态,重启都没用,最后是修复了远程存储才恢复。
4.1.2 top:动态监控,实时刷新
top 是动态的,默认3秒刷新一次。它像是一个实时仪表盘,CPU、内存、负载、进程列表全在上面。
# 直接运行
top
# 按 CPU 使用率排序(进入 top 后按 P)
# 按内存使用率排序(进入 top 后按 M)
# 只看某个用户的进程(进入 top 后按 u,输入用户名)
top 界面上半部分有几个关键指标:
- load average:1分钟、5分钟、15分钟的平均负载。如果1分钟远大于15分钟,说明负载在飙升。
- %us / %sy:用户态CPU和系统态CPU。%sy 太高,说明内核在忙,可能是系统调用太频繁。
- %wa:IO等待。这个值如果持续超过30%,磁盘大概率是瓶颈。
注意:别把 CPU 使用率和系统负载划等号。负载高不一定 CPU 忙,也可能是大量进程在等 IO。我见过有人看到负载高就加 CPU,结果问题根本没解决。
4.1.3 htop:top 的升级版,更直观
htop 不是系统自带的,但强烈建议装上。它支持鼠标操作、颜色区分、树形视图,看着舒服多了。
# 安装(CentOS)
yum install htop -y
# 安装(Ubuntu)
apt install htop -y
# 运行
htop
htop 里我最喜欢的功能是 F5 树形视图,能清楚看到哪个进程是哪个进程生出来的。排查僵尸进程时特别好用——找到父进程,直接干掉它,子进程就由 init 收养了。
4.2 进程控制:该杀就杀,该让就让
4.2.1 kill:发信号,不只是“杀死”
kill 这个名字有点误导人,它其实是给进程发信号。默认信号是 SIGTERM (15),让进程自己收拾干净再退出。实在不行才用 SIGKILL (9),直接暴力砍掉。
# 优雅终止(推荐)
kill 1234
# 强制杀死(最后手段)
kill -9 1234
# 重载配置(比如 nginx 热加载)
kill -HUP 1234
# 暂停进程
kill -STOP 1234
# 继续运行
kill -CONT 1234
我的习惯:先 kill -15,等5秒,不行再 kill -9。直接上 -9 容易丢数据,尤其是数据库进程。有一次我手快 kill -9 了一个 MySQL 进程,结果恢复花了半小时。
4.2.2 nice 与 renice:给进程排优先级
CPU 资源不够分的时候,谁先跑谁后跑,由 nice 值决定。范围是 -20 到 19,值越低优先级越高。普通用户只能调高(更 nice),root 可以调低(更霸道)。
# 启动时指定 nice 值(优先级较高)
nice -n -5 ./myapp
# 调整正在运行的进程(把 PID 1234 的优先级调低)
renice 10 -p 1234
实际场景中,我会把后台批处理任务的 nice 值调高(比如 10),让它们别跟线上服务抢 CPU。反过来,核心数据库进程我会调低 nice 值(比如 -5),保证响应速度。
4.3 系统负载分析:找到真正的瓶颈
4.3.1 uptime:看一眼就知道服务器累不累
uptime 是最简单的命令,输出只有一行,但信息量很大。
$ uptime
14:32:10 up 120 days, 3:15, 2 users, load average: 0.45, 0.62, 0.71
三个负载值分别对应1、5、15分钟的平均值。怎么判断是否正常?
- 负载值 < CPU 核心数:正常,资源充裕。
- 负载值 ≈ CPU 核心数:快满了,需要关注。
- 负载值 > CPU 核心数 * 2:已经过载,必须处理。
举个例子,一台 4 核服务器,负载 8.0,说明平均每个核有 2 个进程在排队。这时候用户访问肯定会觉得卡。
4.3.2 vmstat:虚拟内存和系统整体状况
vmstat 是我排查性能问题时用的最多的命令之一。它把 CPU、内存、IO 的情况浓缩在一张表里。
# 每2秒输出一次,共输出5次
vmstat 2 5
输出示例:
| procs | memory | swap | io | system | cpu |
|---|---|---|---|---|---|
| r b | swpd free buff cache | si so | bi bo | in cs | us sy id wa st |
| 2 0 | 0 123456 7890 45678 | 0 0 | 100 50 | 200 1500 | 30 10 60 0 0 |
关键列解读:
- r(procs):正在排队等 CPU 的进程数。如果这个值持续大于 CPU 核心数,说明 CPU 不够用。
- b(procs):处于不可中断睡眠的进程数。如果这个值一直大于0,IO 大概率有问题。
- si / so(swap):从磁盘交换进/出的内存量。如果这两个值不是0,说明物理内存不够了,系统在频繁换页,性能会急剧下降。
- wa(cpu):IO 等待时间。超过30%就要查磁盘了。
避坑指南:我曾经遇到一个 Java 应用,vmstat 显示 si/so 持续不为0,但 free 命令看内存还有剩余。后来发现是 JVM 的堆外内存没算进去,加上 GC 参数不合理,导致系统不断 swap。调了 JVM 参数后,si/so 立刻归零。
4.3.3 iostat:磁盘到底行不行
当 vmstat 的 wa 偏高时,就该用 iostat 看看具体是哪块磁盘在拖后腿。
# 查看所有磁盘的 IO 统计,每2秒刷新一次
iostat -x 2
重点关注这几个指标:
| 指标 | 含义 | 健康值 |
|---|---|---|
| %util | 磁盘忙绿时间百分比 | < 70% 正常,> 90% 危险 |
| await | IO 请求平均等待时间(ms) | SSD < 5ms,机械盘 < 20ms |
| svctm | IO 请求平均服务时间(ms) | 越接近 await 越好 |
| r/s / w/s | 每秒读/写请求数 | 取决于磁盘规格 |
如果 %util 接近100%但 r/s 不高,说明磁盘本身性能不行,该换了。如果 await 远大于 svctm,说明 IO 队列太长,请求在排队。
4.4 知识体系总览
下面这张图把本章的核心命令和它们之间的关系串起来了。你可以把它当作排查问题的路线图。
4.5 实战排查流程
最后,我总结一个实际排查的步骤,你遇到问题直接照着来:
- 第一步:跑
uptime,看负载是否异常。如果负载正常,可能是应用层的问题,不是系统瓶颈。 - 第二步:跑
vmstat 1 5,看 r、b、wa、si/so 哪个指标异常。 - 第三步:如果 wa 高,跑
iostat -x 1定位磁盘;如果 r 高,跑top看哪个进程在吃 CPU。 - 第四步:用
ps aux找到具体进程,确认是不是预期内的程序。 - 第五步:根据情况用
kill终止异常进程,或用renice调整优先级。
这套流程我用了好多年,从几十台的小集群到上千台的大规模环境,基本没失手过。你把它记熟了,遇到线上故障就不会慌。