Linux 进程管理与性能排查:10 个核心工具实战
说明: 本文为配置思路与示例整理,不代表作者已在自己的服务器上逐项验证全部命令。执行涉及公网暴露、账户权限、数据删除或服务重启的操作前,请先备份,并结合官方文档与实际环境核验。
服务器 CPU 飙到 100%、内存被吃光、磁盘 IO 暴涨——这些问题每天都在发生。掌握进程管理与性能排查工具,是每个运维和开发者的必备技能。本文用真实场景教你 10 个核心工具,从发现问题到定位根因按步骤。
为什么需要掌握进程管理?
想象一下这个场景:凌晨 3 点,你的手机收到告警——服务器响应超时。登上服务器一看:
$ uptime
03:00:01 up 45 days, 3:22, 1 user, load average: 28.47, 22.13, 15.86Load average 超过核心数好几倍,系统几乎瘫痪。这时候你该怎么办?逐个尝试 kill 吗?太慢了。你需要一套系统化的排查流程。
本文将覆盖 10 个核心工具,帮你快速定位问题:
| 工具 | 用途 | 适用场景 |
|---|---|---|
top / htop |
实时监控进程资源 | 快速查看谁在吃资源 |
ps |
查看进程详情 | 精确筛选特定进程 |
pidstat |
进程级性能统计 | 持续监控单个进程 |
lsof |
打开文件列表 | 排查文件句柄泄漏 |
strace |
系统调用追踪 | 排查程序卡死原因 |
vmstat |
系统整体性能 | 判断瓶颈类型 |
iostat |
磁盘 IO 统计 | 排查磁盘性能问题 |
nice / renice |
调整进程优先级 | 降低关键进程 CPU 优先级 |
nohup / screen / tmux |
后台运行进程 | 防止进程随终端断开退出 |
systemd |
服务生命周期管理 | 进程守护与自启动 |
场景一:CPU 100% 怎么排查?
第一步:用 top 快速定位
top按下 P(大写)按 CPU 使用率排序,你会看到类似这样的输出:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3847 root 20 0 892340 312068 18232 R 100.0 3.1 45:23.01 java
1023 www 20 0 456120 128904 12056 S 12.3 1.3 8:45:33 nginxjava 进程吃满了 CPU。记下它的 PID:3847。
第二步:用 ps 查看完整命令行
ps -fp 3847 -o pid,ppid,user,%cpu,%mem,start,time,cmd PID PPID USER %CPU %MEM STARTED TIME CMD
3847 1001 root 100.0 3.1 Apr28 45:23:01 java -Xmx2g -jar app.jar第三步:用 strace 看它在干什么
# 追踪 10 秒,看系统调用统计
strace -c -p 3847 -e trace=all &
sleep 10
kill %1输出类似:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
45.23 2.345678 123 19070 futex
23.11 1.201234 89 13497 epoll_wait
12.45 0.647890 45 14397 read
8.67 0.451234 67 6735 write
5.34 0.277890 34 8173 mmap
3.12 0.162345 28 5798 munmap
2.08 0.108234 21 5154 close
------ ----------- ----------- --------- --------- ----------------
100.00 5.194545 72824 total关键发现:大量 futex 调用 = 程序在疯狂抢锁,很可能是 死锁 或 锁竞争。
第四步:查看 Java 线程堆栈
jstack 3847 > /tmp/thread_dump.txt
grep -A 20 "BLOCKED" /tmp/thread_dump.txt | head -60这样就能找到具体是哪些线程在等锁。
场景二:内存被吃光了
用 free 快速判断
free -h total used free shared buff/cache available
Mem: 15Gi 14Gi 98Mi 256Mi 1.2Gi 856Mi
Swap: 4.0Gi 3.8Gi 20Mi危险信号:可用内存只剩 856Mi,Swap 已用 3.8G。
找出内存大户
# 按 RSS(实际物理内存)排序,取前 10
ps aux --sort=-%mem | head -11USER PID %CPU %MEM RSS VSZ TTY STAT START TIME COMMAND
root 3847 100.0 18.2 2891200 6401000 ? Sl Apr28 45:23 java -Xmx2g -jar app.jar
root 5621 2.3 8.5 1345600 2890000 ? S 03:00 0:45 node server.js
www 1023 12.3 5.1 812340 456120 ? S Apr28 8:45 nginx: worker用 top 的 M 键排序
在 top 界面按 M(大写),按内存排序查看。
检查是否有内存泄漏
# 每 5 秒记录一次进程内存使用
while true; do
ps -p 3847 -o pid,rss,vsz,etime --no-headers
sleep 5
done如果 RSS 持续增长不回落,就是内存泄漏。
场景三:磁盘 IO 飙高
用 iostat 看磁盘状态
# 每 2 秒刷新一次,共 5 次
iostat -xz 2 5重点关注这几列:
Device r/s w/s rkB/s wkB/s await svctm %util
sda 156.00 234.00 4896.00 15680.00 45.23 3.12 98.50
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00关键指标:
- %util > 80%:磁盘已经接近满负荷
- await > 10ms:IO 延迟偏高
- r/s + w/s:每秒读写次数
找出谁在大量读写磁盘
# 安装 iotop(需要 root)
apt install iotop -y
iotop -oPTotal DISK READ: 15.32 M/s | Total DISK WRITE: 42.89 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
3847 be/4 root 15.32 M/s 42.89 M/s 0.00 % 98.50 % java -Xmx2g -jar app.jar用 lsof 找打开的文件
# 找进程打开的文件数
lsof -p 3847 | wc -l
# 找进程打开的特定类型文件
lsof -p 3847 | grep -E '\.(log|tmp|dat)' | head -20
# 找占用某目录的进程
lsof +D /var/log/ | head -20场景四:进程卡死不响应
用 strace 追踪系统调用
# 追踪进程的实时系统调用
strace -p 3847 -f -e trace=network,read,write如果输出停住不动,说明进程卡在某个系统调用上。
常见卡死原因
| 现象 | strace 输出 | 原因 |
|---|---|---|
卡在 futex |
futex(0x7fff..., FUTEX_WAIT, ...) |
死锁 |
卡在 read |
read(5, ... |
等待网络数据/管道 |
卡在 epoll_wait |
epoll_wait(7, ...) |
正常空闲(不一定卡死) |
卡在 connect |
connect(5, {sa_family=AF_INET, ...}) |
网络连接超时 |
卡在 nanosleep |
nanosleep({tv_sec=300, ...}) |
正在 sleep |
场景五:进程优先级管理
调低非关键进程的 CPU 优先级
# 降低进程的调度优先级(-20 最高,19 最低)
renice 15 -p 3847
# 或者用 nice 启动时指定
nice -n 15 java -jar background-task.jar &
# 极端情况:暂停/恢复进程
kill -STOP 3847 # 暂停
kill -CONT 3847 # 恢复真实场景
假设你有一个批量数据处理脚本和一个 Web 服务跑在同一台机器上:
# 数据处理脚本降低优先级
nice -n 15 python3 batch_process.py &
# Web 服务保持默认优先级
java -jar web-app.jar &
# Web 服务紧急降级(如果数据处理脚本影响了 Web 响应)
renice 15 -p $(pgrep -f batch_process.py)实用技巧速查
批量操作
# 杀掉所有匹配的进程
pkill -f "old-process-name"
# 杀掉某个用户的所有进程
killall -u username
# 按 CPU 使用率杀进程(>90% 的非关键进程)
ps aux | awk '$3 > 90 && $11 != "java" {print $2}' | xargs -r kill进程树查看
# 查看进程树
pstree -p
# 查看某个进程的子进程
pstree -p 1
# 查看某个进程的父进程
ps -o ppid= -p 3847后台进程管理
# 方法一:nohup + &(最简单)
nohup java -jar app.jar > /var/log/app.log 2>&1 &
# 方法二:screen(可重新连接)
screen -S myapp
java -jar app.jar
# Ctrl+A, D 分离
# screen -r myapp 重新连接
# 方法三:tmux(screen 的现代替代)
tmux new -s myapp
java -jar app.jar
# Ctrl+B, D 分离
# tmux attach -t myapp 重新连接
# 方法四:systemd(生产环境推荐)
# 见下文systemd 服务管理(生产环境首选)
创建一个 systemd 服务文件:
sudo vim /etc/systemd/system/myapp.service[Unit]
Description=My Application
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/java -Xmx2g -jar /opt/myapp/app.jar
ExecStop=/bin/kill -TERM $MAINPID
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
# 安全限制
LimitNOFILE=65535
LimitNPROC=4096
[Install]
WantedBy=multi-user.target# 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
# 查看状态和日志
sudo systemctl status myapp
sudo journalctl -u myapp -f一键排查脚本
最后分享一个我常用的快速排查脚本:
#!/bin/bash
# quick-diag.sh - 服务器快速诊断
echo "========== 系统负载 =========="
uptime
echo -e "\n========== 内存使用 =========="
free -h
echo -e "\n========== 磁盘使用 =========="
df -h | grep -E '^/dev'
echo -e "\n========== CPU TOP 5 =========="
ps aux --sort=-%cpu | head -6
echo -e "\n========== 内存 TOP 5 =========="
ps aux --sort=-%mem | head -6
echo -e "\n========== IO 最高的磁盘 =========="
iostat -x 1 1 | grep -E '^(sd|vd|nvme)'
echo -e "\n========== 最近的 OOM 记录 =========="
dmesg | grep -i "out of memory" | tail -5
echo -e "\n========== 文件描述符使用 =========="
echo "系统级: $(cat /proc/sys/fs/file-nr)"
for pid in $(ps -eo pid --no-headers | head -10); do
count=$(ls /proc/$pid/fd 2>/dev/null | wc -l)
name=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' ' | head -c 50)
[ "$count" -gt 100 ] && echo "PID $pid ($count fd): $name"
donechmod +x quick-diag.sh
./quick-diag.sh总结
| 场景 | 推荐工具链 | 关键命令 |
|---|---|---|
| CPU 100% | top → ps → strace → jstack |
top -Hp PID |
| 内存泄漏 | free → ps aux --sort=-%mem |
watch -n 5 'ps -p PID -o rss' |
| 磁盘 IO 高 | iostat → iotop → lsof |
iostat -xz 2 |
| 进程卡死 | strace -p PID |
看卡在哪个系统调用 |
| 优先级调整 | nice → renice |
renice 15 -p PID |
| 后台运行 | nohup / tmux / systemd |
生产用 systemd |
| 快速诊断 | 一键脚本 | uptime + free + ps |
掌握这些工具后,遇到服务器问题不再是"重启试试",而是5 分钟内精准定位根因。
💡 建议收藏本文,遇到问题时对照排查。如果有更好的排查技巧,欢迎留言分享!
评论
游客无需注册即可评论。
你提交的昵称、邮箱、网址和评论内容会保存在服务端,用于展示评论身份、接收回复及必要的安全审计。
浏览器会本地保存已填游客信息和评论草稿,方便下次免填。
回复提醒会通过站内消息和邮件通知。