Linux 进程资源占用分析指南
本文档介绍在 Linux 系统下如何分析和监控进程的资源占用情况,包括 CPU、内存、I/O 等关键指标的查看方法。
目录
快速开始
前提条件
-
已知进程 ID (PID)
-
获取 PID 的方法:
bash# 通过进程名查找 pgrep process_name ps aux | grep process_name # 通过端口查找 lsof -i :port netstat -tlnp | grep :port
命令行工具
1. top 命令(实时监控)
基本用法:
bash
top -p PID
交互式操作:
1- 显示每个 CPU 核心的使用情况c- 切换显示完整命令行M- 按内存使用排序P- 按 CPU 使用排序f- 添加或删除显示的字段q- 退出
输出说明:
%CPU- CPU 使用百分比%MEM- 内存使用百分比VIRT- 虚拟内存大小RES- 物理内存使用(RSS)SHR- 共享内存
2. htop(增强版 top,推荐)
基本用法:
bash
htop -p PID
功能特点:
- 更直观的彩色界面
- 树状视图显示进程关系(按
F5) - 可直接查看进程打开的文件(按
F2添加列) - 支持鼠标操作
- 实时显示 CPU 和内存使用率
快捷键:
F2- 设置F5- 树状视图F6- 排序选择F9- 发送信号F10- 退出
3. ps 命令(快照查看)
基本资源查看:
bash
ps -p PID -o pid,ppid,%cpu,%mem,vsz,rss,cmd
详细资源报告:
bash
ps -p PID -o user,pid,ppid,ni,%cpu,%mem,vsz,rss,tty,stat,start,time,cmd,etime
字段说明:
pid- 进程 IDppid- 父进程 ID%cpu- CPU 使用百分比%mem- 内存使用百分比vsz- 虚拟内存大小(KB)rss- 物理内存使用(KB)cmd- 完整命令行etime- 进程运行时间stat- 进程状态
连续监控:
bash
watch -n 1 'ps -p PID -o pid,%cpu,%mem,vsz,rss,cmd'
4. pidstat(详细资源统计)
安装:
bash
# Ubuntu/Debian
sudo apt-get install sysstat
# CentOS/RHEL
sudo yum install sysstat
基本用法:
bash
# 每2秒刷新一次,共显示5次
pidstat -p PID 2 5
详细资源监控:
bash
# 磁盘 I/O 统计
pidstat -d -p PID
# 内存页错误统计
pidstat -r -p PID
# 栈使用统计
pidstat -s -p PID
# 线程级统计
pidstat -t -p PID
# 综合统计(CPU、内存、I/O)
pidstat -u -r -d -p PID 2 5
输出指标:
%usr- 用户态 CPU 使用率%system- 内核态 CPU 使用率%guest- 虚拟化 CPU 使用率%CPU- 总 CPU 使用率minflt/s- 次要页错误率majflt/s- 主要页错误率VSZ- 虚拟内存大小RSS- 物理内存使用kB_rd/s- 读取速率(KB/s)kB_wr/s- 写入速率(KB/s)
5. atop(高级监控)
安装:
bash
# Ubuntu/Debian
sudo apt-get install atop
# CentOS/RHEL
sudo yum install atop
基本用法:
bash
atop -p PID
功能亮点:
- 显示磁盘负载详情
- 网络带宽使用统计
- 进程级 GPU 使用(需插件支持)
- 历史资源记录(按
t切换时间点) - 支持记录和回放
快捷键:
t- 切换时间点m- 显示内存信息d- 显示磁盘信息n- 显示网络信息q- 退出
6. nmon(可视化监控)
安装:
bash
# Ubuntu/Debian
sudo apt-get install nmon
# CentOS/RHEL
sudo yum install nmon
基本用法:
bash
nmon -p PID
交互式界面:
c- 查看 CPU 使用情况m- 查看内存使用情况d- 查看磁盘 I/On- 查看网络统计t- 查看进程/线程统计q- 退出
7. iotop(I/O 监控)
安装:
bash
# Ubuntu/Debian
sudo apt-get install iotop
# CentOS/RHEL
sudo yum install iotop
基本用法:
bash
# 实时监控指定进程的 I/O
iotop -p PID
# 显示累计 I/O
iotop -a -p PID
输出说明:
DISK READ- 磁盘读取速率DISK WRITE- 磁盘写入速率SWAPIN- 交换分区使用率IO- I/O 使用百分比
8. lsof(列出打开文件)
基本用法:
bash
# 查看进程打开的所有文件
lsof -p PID
# 查看进程打开的网络连接
lsof -p PID -i
# 查看进程打开的文件描述符数量
lsof -p PID | wc -l
# 查看进程打开的具体文件类型
lsof -p PID | grep -E 'REG|DIR|CHR|FIFO|SOCK'
# 查看进程的端口占用
lsof -p PID -iTCP -sTCP:LISTEN
# 查看进程的工作目录
lsof -p PID | grep cwd
# 查看进程打开的文件并按类型统计
lsof -p PID | awk '{print $5}' | sort | uniq -c
字段说明:
COMMAND- 命令名PID- 进程 IDUSER- 用户FD- 文件描述符TYPE- 文件类型(REG=普通文件, DIR=目录, CHR=字符设备等)DEVICE- 设备号SIZE/OFF- 文件大小或偏移量NODE- inode 号NAME- 文件路径
9. sar(系统活动报告)
安装:
bash
# Ubuntu/Debian
sudo apt-get install sysstat
# CentOS/RHEL
sudo yum install sysstat
基本用法:
bash
# 查看当前 CPU 使用(每1秒刷新,共5次)
sar -u 1 5
# 查看内存使用
sar -r 1 5
# 查看 I/O 统计
sar -b 1 5
# 查看进程相关统计
sar -x PID 1 5
# 查看历史数据(需要启用 sysstat 数据收集)
sar -u
sar -r
sar -b
# 生成综合报告
sar -A > sar_report.txt
优势:
- 可以查看历史性能数据
- 适合长期监控和趋势分析
- 数据可以保存和回放
10. vmstat(虚拟内存统计)
基本用法:
bash
# 每2秒刷新一次,共显示5次
vmstat 2 5
# 查看进程相关统计
vmstat -p /dev/sda1 2 5
# 显示详细的内存统计
vmstat -s
输出说明:
procs- 进程统计(r=运行队列, b=阻塞)memory- 内存统计(swpd=交换分区, free=空闲内存)swap- 交换分区使用io- I/O 统计(bi=块读取, bo=块写入)system- 系统统计(in=中断, cs=上下文切换)cpu- CPU 使用百分比
11. pmap(内存映射查看)
基本用法:
bash
# 查看进程的内存映射
pmap -x PID
# 显示详细信息
pmap -XX PID
# 显示设备格式
pmap -d PID
# 显示扩展格式
pmap -X PID
# 查看内存映射摘要
pmap -q PID
输出说明:
Address- 内存地址范围Kbytes- 内存大小(KB)RSS- 实际物理内存(KB)Dirty- 脏页大小(KB)Mode- 内存权限(r=读, w=写, x=执行, s=共享, p=私有)Mapping- 映射的文件或设备
用途:
- 分析内存占用分布
- 查找内存泄漏
- 查看共享库占用
12. smem(内存使用统计)
安装:
bash
# Ubuntu/Debian
sudo apt-get install smem
# CentOS/RHEL
sudo yum install smem
基本用法:
bash
# 查看进程内存使用(按 PSS 排序)
smem -P process_name
# 查看指定 PID 的内存使用
smem -p PID
# 显示详细统计
smem -t -k -p PID
# 按用户统计
smem -u
# 生成报告
smem -t -k -P process_name -c "pid user command pss rss"
优势:
- PSS (Proportional Set Size): 更准确的内存统计,考虑了共享内存
- USS (Unique Set Size): 进程独占的内存
- RSS (Resident Set Size): 实际物理内存
13. ss(现代网络连接工具)
基本用法:
bash
# 查看进程的网络连接
ss -tulpn | grep PID
# 查看 TCP 连接
ss -tpn | grep PID
# 查看 UDP 连接
ss -upn | grep PID
# 显示详细信息
ss -tulnap | grep PID
# 查看监听端口
ss -tlnp | grep PID
# 统计连接数
ss -s
相比 netstat 的优势:
- 更快速
- 显示更多信息
- 更好的过滤选项
14. time 命令(执行时间统计)
基本用法:
bash
# 使用 time 命令运行程序并统计资源
time command
# 使用 /usr/bin/time 获取更详细信息
/usr/bin/time -v command
# 查看进程运行时间
time -p sleep 5
# 详细资源统计
/usr/bin/time -f "%E real, %U user, %S sys, %M KB memory" command
输出说明:
real- 实际运行时间(墙钟时间)user- 用户态 CPU 时间sys- 内核态 CPU 时间%M- 最大内存使用(KB)
15. taskset / numactl(CPU 亲和性和 NUMA)
基本用法:
bash
# 查看进程的 CPU 亲和性
taskset -p PID
# 查看进程的 NUMA 节点
numactl --show
# 查看进程的 NUMA 统计
numastat -p PID
# 查看系统 NUMA 信息
numactl --hardware
用途:
- 优化进程的 CPU 绑定
- 在 NUMA 系统上优化内存访问
- 提高缓存命中率
16. prlimit(资源限制查看)
基本用法:
bash
# 查看进程的资源限制
prlimit --pid=PID
# 查看特定资源限制
prlimit --pid=PID --as # 虚拟内存限制
prlimit --pid=PID --rss # 物理内存限制
prlimit --pid=PID --nofile # 文件描述符限制
prlimit --pid=PID --cpu # CPU 时间限制
常用资源限制:
AS- 虚拟内存大小RSS- 物理内存大小NOFILE- 文件描述符数量CPU- CPU 时间(秒)NPROC- 进程数限制
17. systemd-cgtop(systemd 进程组监控)
基本用法:
bash
# 查看 systemd 管理的进程组资源使用
systemd-cgtop
# 查看特定服务的资源使用
systemd-cgtop /system.slice/service-name.service
# 查看用户服务的资源使用
systemd-cgtop /user.slice/user-1000.slice
适用场景:
- 监控 systemd 管理的服务
- 查看容器资源使用(如果使用 systemd-nspawn)
- 分析服务资源消耗
18. slabtop(内核 slab 缓存监控)
基本用法:
bash
# 实时查看内核 slab 缓存使用
slabtop
# 按使用量排序
slabtop -s c
# 只显示正在使用的缓存
slabtop -o
用途:
- 诊断内核内存泄漏
- 查看内核缓存使用情况
- 分析系统内存压力
系统文件分析
/proc 文件系统(底层信息)
/proc/PID/ 目录提供了进程的详细底层信息。
CPU 使用情况
bash
# 查看进程 CPU 时间统计
cat /proc/PID/stat | awk '{print "用户态CPU: " $14 " 时钟周期"; print "内核态CPU: " $15 " 时钟周期"}'
# 实时监控 CPU 使用率
while true; do
cat /proc/PID/stat | awk '{utime=$14; stime=$15; total=$14+$15; print "用户态: " utime " 内核态: " stime " 总计: " total}'
sleep 1
done
内存使用情况
bash
# 查看内存详细信息
cat /proc/PID/status | grep -E 'VmPeak|VmSize|VmRSS|VmSwap|VmHWM|VmData|VmStk|VmExe'
# 字段说明:
# VmPeak - 虚拟内存峰值(KB)
# VmSize - 当前虚拟内存大小(KB)
# VmRSS - 实际物理内存使用(KB)
# VmSwap - 交换分区使用(KB)
# VmHWM - 物理内存峰值(KB)
# VmData - 数据段大小(KB)
# VmStk - 栈大小(KB)
# VmExe - 可执行文件大小(KB)
打开文件描述符
bash
# 查看打开的文件描述符数量
ls -l /proc/PID/fd | wc -l
# 查看具体打开的文件
ls -l /proc/PID/fd
# 查看打开的文件列表(带路径)
for fd in /proc/PID/fd/*; do
readlink -f "$fd"
done
I/O 统计
bash
# 查看 I/O 统计信息
cat /proc/PID/io
# 输出字段说明:
# rchar - 读取字符数(包括缓存)
# wchar - 写入字符数(包括缓存)
# syscr - 系统调用读取次数
# syscw - 系统调用写入次数
# read_bytes - 实际磁盘读取字节数
# write_bytes - 实际磁盘写入字节数
# cancelled_write_bytes - 取消的写入字节数
线程信息
bash
# 查看线程数量
ls /proc/PID/task | wc -l
# 查看每个线程的详细信息
for tid in /proc/PID/task/*; do
echo "线程 ID: $(basename $tid)"
cat $tid/stat | awk '{print "CPU时间: " $14+$15}'
done
上下文切换
bash
# 查看上下文切换统计
cat /proc/PID/status | grep -E 'voluntary_ctxt_switches|nonvoluntary_ctxt_switches'
# 字段说明:
# voluntary_ctxt_switches - 自愿上下文切换(等待资源)
# nonvoluntary_ctxt_switches - 非自愿上下文切换(时间片到期)
网络连接
bash
# 查看进程的网络连接
cat /proc/PID/net/tcp
cat /proc/PID/net/udp
# 或使用 netstat/lsof
netstat -anp | grep PID
lsof -p PID -i
资源限制
bash
# 查看进程的资源限制
cat /proc/PID/limits
# 字段说明:
# Limit - 资源类型
# Soft Limit - 软限制(可超过但会收到信号)
# Hard Limit - 硬限制(不可超过)
# Units - 单位
环境变量
bash
# 查看进程的环境变量
cat /proc/PID/environ | tr '\0' '\n'
# 查找特定环境变量
cat /proc/PID/environ | tr '\0' '\n' | grep VARIABLE_NAME
命令行和工作目录
bash
# 查看命令行参数
cat /proc/PID/cmdline | tr '\0' ' '
# 查看工作目录
readlink /proc/PID/cwd
# 查看可执行文件路径
readlink /proc/PID/exe
内存映射详情
bash
# 查看详细的内存映射
cat /proc/PID/maps
# 查看内存映射摘要
cat /proc/PID/smaps
# smaps 提供更详细的信息:
# - 每个映射区域的详细统计
# - 共享/私有内存大小
# - 脏页统计
# - 交换分区使用
进程关系
bash
# 查看进程树
pstree -p PID
# 查看子进程
ps --ppid PID
# 查看进程会话和进程组
cat /proc/PID/stat | awk '{print "会话ID: " $6 " 进程组: " $5}'
Cgroup 资源监控
Cgroup v1 文件系统
如果进程在 cgroup 中运行(如 Docker 容器、systemd 服务),可以通过 cgroup 文件系统查看资源使用:
bash
# 查找进程的 cgroup 路径
cat /proc/PID/cgroup
# 查看 CPU 使用(如果使用 CPU cgroup)
cat /sys/fs/cgroup/cpu/cgroup_name/cpuacct.usage
cat /sys/fs/cgroup/cpu/cgroup_name/cpu.stat
# 查看内存使用(如果使用 Memory cgroup)
cat /sys/fs/cgroup/memory/cgroup_name/memory.usage_in_bytes
cat /sys/fs/cgroup/memory/cgroup_name/memory.stat
cat /sys/fs/cgroup/memory/cgroup_name/memory.limit_in_bytes
# 查看 I/O 统计(如果使用 blkio cgroup)
cat /sys/fs/cgroup/blkio/cgroup_name/blkio.io_service_bytes
cat /sys/fs/cgroup/blkio/cgroup_name/blkio.io_serviced
# 查看进程数限制
cat /sys/fs/cgroup/pids/cgroup_name/pids.current
cat /sys/fs/cgroup/pids/cgroup_name/pids.max
Cgroup v2 文件系统
现代 Linux 系统使用 cgroup v2:
bash
# 查找进程的 cgroup 路径
cat /proc/PID/cgroup
# 查看资源统计(统一接口)
cat /sys/fs/cgroup/cgroup_name/cpu.stat
cat /sys/fs/cgroup/cgroup_name/memory.current
cat /sys/fs/cgroup/cgroup_name/memory.stat
cat /sys/fs/cgroup/cgroup_name/io.stat
# 查看资源限制
cat /sys/fs/cgroup/cgroup_name/memory.max
cat /sys/fs/cgroup/cgroup_name/cpu.max
systemd 服务资源监控
bash
# 查看服务的资源使用
systemd-cgtop
# 查看特定服务的统计
systemctl status service-name
systemd-cgtop /system.slice/service-name.service
# 查看服务资源限制配置
systemctl show service-name | grep -i limit
Docker 容器资源监控
bash
# 查看容器的资源使用
docker stats container_name
# 查看容器的详细资源统计
docker stats --no-stream container_name
# 查看容器的 cgroup 信息
docker inspect container_name | grep -i cgroup
# 进入容器查看
docker exec container_name cat /proc/self/cgroup
高级监控工具
bpftrace(动态追踪)
安装:
bash
# Ubuntu 20.04+
sudo apt-get install bpftrace
# 或从源码编译
基本用法:
bash
# 实时监控 CPU 使用(按用户态堆栈)
bpftrace -e 'profile:hz:99 /pid == PID/ { @[ustack] = count(); }'
# 监控系统调用
bpftrace -e 'tracepoint:syscalls:sys_enter_* /pid == PID/ { @[probe] = count(); }'
# 监控 I/O 操作
bpftrace -e 'tracepoint:block:block_rq_issue /pid == PID/ { @[comm] = count(); }'
# 监控内存分配
bpftrace -e 'uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc /pid == PID/ { @[ustack] = count(); }'
perf(性能分析)
安装:
bash
# Ubuntu/Debian
sudo apt-get install linux-perf
# CentOS/RHEL
sudo yum install perf
基本用法:
bash
# 实时查看热点函数
perf top -p PID
# 记录性能数据
perf record -p PID -g sleep 10
# 查看报告
perf report
# 统计系统调用
perf stat -p PID sleep 5
# 追踪特定事件
perf trace -p PID
strace(系统调用追踪)
基本用法:
bash
# 追踪系统调用并统计
strace -cp PID
# 追踪特定系统调用
strace -e trace=open,read,write -p PID
# 显示时间戳
strace -t -p PID
# 统计系统调用耗时
strace -c -p PID
关键指标说明
指标对照表
| 指标 | 命令/文件 | 说明 | 正常范围参考 |
|---|---|---|---|
| CPU 使用 | ps -o %cpu |
进程占用 CPU 百分比 | 0-100% |
| 内存使用 | ps -o %mem,rss,vsz |
%mem=物理内存百分比,rss=实际物理内存(KB),vsz=虚拟内存大小(KB) | 根据系统内存调整 |
| 线程数 | ls /proc/PID/task |
任务目录数量即为线程数 | 根据应用类型 |
| I/O 读取 | /proc/PID/io |
read_bytes 显示实际磁盘读取 | 根据应用需求 |
| I/O 写入 | /proc/PID/io |
write_bytes 显示实际磁盘写入 | 根据应用需求 |
| 上下文切换 | /proc/PID/status |
voluntary_ctxt_switches/nonvoluntary_ctxt_switches | 过高可能存在问题 |
| 运行时间 | ps -o etime |
进程已运行时间 (格式: [[DD-]hh:]mm:ss) | - |
| 文件描述符 | ls /proc/PID/fd |
打开的文件描述符数量 | 注意是否有泄漏 |
内存相关指标详解
- VIRT (Virtual Memory Size): 进程使用的虚拟内存总量,包括代码、数据、共享库等
- RES (Resident Set Size): 进程实际使用的物理内存,不包括交换分区
- SHR (Shared Memory): 共享内存大小,可能被多个进程共享
- %MEM: RES 占系统总物理内存的百分比
CPU 相关指标详解
- %CPU: 进程在采样周期内的 CPU 使用百分比,可能超过 100%(多核系统)
- 用户态时间: 进程在用户空间执行的时间
- 内核态时间: 进程在内核空间执行的时间(系统调用)
常见问题排查
1. CPU 使用率过高
诊断步骤:
bash
# 查看 CPU 热点函数
perf top -p PID
# 统计系统调用
strace -cp PID
# 查看线程 CPU 使用
top -H -p PID
# 使用 bpftrace 追踪
bpftrace -e 'profile:hz:99 /pid == PID/ { @[ustack] = count(); }'
可能原因:
- 无限循环或死循环
- 频繁的系统调用
- 计算密集型任务
- 锁竞争导致的忙等待
2. 内存使用过高
诊断步骤:
bash
# 查看详细内存映射
pmap -x PID
# 查看内存使用趋势
watch -n 1 'ps -p PID -o pid,%mem,rss,vsz'
# 使用 gdb 查看内存区域
gdb -p PID -ex "info proc mappings" --batch
# 检查内存泄漏(需要持续监控)
valgrind --leak-check=full ./program
可能原因:
- 内存泄漏
- 缓存过大
- 数据结构设计不合理
- 内存碎片
3. I/O 瓶颈
诊断步骤:
bash
# 实时监控 I/O
iotop -p PID
# 查看 I/O 统计
cat /proc/PID/io
# 使用 SystemTap 追踪文件操作(需要 root)
stap -e 'probe vfs.* { if (pid() == PID) printf("%s\n", pp()) }'
# 查看磁盘使用情况
iostat -x 1
可能原因:
- 频繁的小文件读写
- 未使用缓冲
- 磁盘性能瓶颈
- 网络 I/O 延迟
4. 线程/进程过多
诊断步骤:
bash
# 查看线程数量
ls /proc/PID/task | wc -l
# 查看线程详情
ps -T -p PID
# 查看进程树
pstree -p PID
5. 文件描述符泄漏
诊断步骤:
bash
# 监控文件描述符数量
watch -n 1 'ls /proc/PID/fd | wc -l'
# 查看打开的文件
lsof -p PID
# 查看具体文件类型分布
ls -l /proc/PID/fd | awk '{print $NF}' | xargs -I {} readlink {} | sort | uniq -c
自动化监控脚本
综合监控脚本
创建一个综合监控脚本,定期采集进程的各项资源指标:
bash
#!/bin/bash
# 进程资源监控脚本
# 用法: ./monitor_process.sh <PID> [interval] [count]
if [ -z "$1" ]; then
echo "用法: $0 <PID> [刷新间隔(秒)] [监控次数]"
echo "示例: $0 12345 2 10"
exit 1
fi
PID=$1
INTERVAL=${2:-2}
COUNT=${3:-5}
# 检查进程是否存在
if ! kill -0 $PID 2>/dev/null; then
echo "错误: 进程 $PID 不存在"
exit 1
fi
echo "===== 进程 $PID 资源监控 (每 ${INTERVAL} 秒刷新,共 ${COUNT} 次) ====="
echo ""
for i in $(seq 1 $COUNT); do
echo "--- 第 $i 次监控 ($(date '+%Y-%m-%d %H:%M:%S')) ---"
# 基本信息
echo "【基本信息】"
ps -p $PID -o user,pid,ppid,ni,%cpu,%mem,vsz,rss,tty,stat,start,time,cmd --no-headers 2>/dev/null || echo "进程已结束"
# CPU 使用
if [ -f /proc/$PID/stat ]; then
echo -e "\n【CPU 使用】"
cat /proc/$PID/stat | awk '{
utime = $14
stime = $15
cutime = $16
cstime = $17
total = utime + stime + cutime + cstime
printf "用户态CPU: %d 时钟周期\n", utime
printf "内核态CPU: %d 时钟周期\n", stime
printf "子进程用户态: %d 时钟周期\n", cutime
printf "子进程内核态: %d 时钟周期\n", cstime
printf "总CPU时间: %d 时钟周期\n", total
}'
fi
# 内存使用
if [ -f /proc/$PID/status ]; then
echo -e "\n【内存使用】"
grep -E 'VmPeak|VmSize|VmRSS|VmSwap|VmHWM|VmData|VmStk|VmExe' /proc/$PID/status
fi
# I/O 统计
if [ -f /proc/$PID/io ]; then
echo -e "\n【I/O 统计】"
cat /proc/$PID/io
fi
# 打开文件描述符
if [ -d /proc/$PID/fd ]; then
echo -e "\n【打开文件描述符数量】"
echo "$(ls -l /proc/$PID/fd 2>/dev/null | wc -l) 个"
fi
# 线程数
if [ -d /proc/$PID/task ]; then
echo -e "\n【线程数】"
echo "$(ls /proc/$PID/task 2>/dev/null | wc -l) 个"
fi
# 上下文切换
if [ -f /proc/$PID/status ]; then
echo -e "\n【上下文切换】"
grep -E 'voluntary_ctxt_switches|nonvoluntary_ctxt_switches' /proc/$PID/status
fi
echo ""
echo "=========================================="
echo ""
if [ $i -lt $COUNT ]; then
sleep $INTERVAL
fi
done
echo "监控完成"
保存监控数据脚本
bash
#!/bin/bash
# 将监控数据保存到文件
# 用法: ./save_monitor.sh <PID> <output_file> [interval]
PID=$1
OUTPUT=${2:-"monitor_${PID}_$(date +%Y%m%d_%H%M%S).log"}
INTERVAL=${3:-5}
echo "开始监控进程 $PID,数据保存到 $OUTPUT"
echo "监控间隔: ${INTERVAL} 秒,按 Ctrl+C 停止"
while true; do
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# 检查进程是否存在
if ! kill -0 $PID 2>/dev/null; then
echo "[$TIMESTAMP] 进程已结束" >> "$OUTPUT"
break
fi
# 采集数据
{
echo "===== $TIMESTAMP ====="
ps -p $PID -o pid,%cpu,%mem,vsz,rss,cmd --no-headers
[ -f /proc/$PID/status ] && grep -E 'VmRSS|VmSize' /proc/$PID/status
[ -f /proc/$PID/io ] && cat /proc/$PID/io
echo ""
} >> "$OUTPUT"
sleep $INTERVAL
done
echo "监控数据已保存到 $OUTPUT"
工具选择建议
根据不同场景选择合适的工具:
| 场景 | 推荐工具 | 说明 |
|---|---|---|
| 快速查看 | ps |
简单快速,适合脚本集成 |
| 实时监控 | htop 或 top |
交互式界面,适合手动监控 |
| 详细统计 | pidstat |
适合定期采样和数据分析 |
| 历史数据 | sar |
查看历史性能数据,适合趋势分析 |
| I/O 分析 | iotop |
专门用于 I/O 监控 |
| 内存分析 | pmap、smem |
pmap 查看内存映射,smem 提供更准确的内存统计 |
| 网络连接 | ss、lsof |
ss 更现代快速,lsof 功能更全面 |
| 文件描述符 | lsof |
查看进程打开的文件和网络连接 |
| 综合监控 | atop |
功能全面,适合系统管理员 |
| 性能分析 | perf 或 bpftrace |
适合深度性能调优 |
| 系统调用 | strace |
追踪和统计系统调用 |
| 资源限制 | prlimit |
查看和设置进程资源限制 |
| CPU 亲和性 | taskset、numactl |
查看和设置 CPU 绑定和 NUMA |
| 容器监控 | docker stats、cgroup |
监控容器资源使用 |
| systemd 服务 | systemd-cgtop |
监控 systemd 管理的服务 |
| 自动化 | /proc 文件系统 |
适合脚本和自动化工具 |
| 问题排查 | strace + perf + pmap |
综合工具定位性能问题 |
总结
分析 Linux 进程资源占用有多种方法,选择合适的工具可以事半功倍:
常用方法分类
-
日常监控:
- 实时监控:
htop、top、atop - 快照查看:
ps、pidstat - 历史数据:
sar(需启用 sysstat 数据收集)
- 实时监控:
-
专项分析:
- 内存 :
pmap(内存映射)、smem(准确统计)、/proc/PID/smaps(详细映射) - I/O :
iotop、pidstat -d、/proc/PID/io - 网络 :
ss、lsof -i、netstat - 文件 :
lsof、/proc/PID/fd
- 内存 :
-
脚本集成:
/proc文件系统:最底层的信息源,适合自动化ps命令:简单快速,输出格式统一pidstat:适合定期采样
-
性能分析:
perf:功能强大的性能分析工具bpftrace:动态追踪,灵活强大strace:系统调用追踪
-
容器和服务监控:
- Docker:
docker stats、cgroup 文件系统 - systemd:
systemd-cgtop、systemctl status - Cgroup:
/sys/fs/cgroup/文件系统
- Docker:
-
系统级监控:
vmstat:系统整体资源统计sar:历史性能数据slabtop:内核缓存监控
关键指标
- CPU :
%cpu、用户态/内核态时间、CPU 亲和性 - 内存 :
RSS(物理内存)、VSZ(虚拟内存)、PSS(比例集大小)、内存映射 - I/O :
read_bytes、write_bytes、I/O 速率 - 网络: 连接数、连接状态、端口占用
- 其他: 线程数、文件描述符数、上下文切换次数、资源限制
最佳实践
- 定期监控:建立监控机制,定期采集关键指标
- 建立基线:记录正常情况下的资源使用,便于对比
- 组合使用:根据问题类型组合使用多个工具
- 自动化:使用脚本自动化监控和告警
- 历史数据 :启用
sar数据收集,便于问题回溯 - 容器环境:在容器环境中使用 cgroup 相关工具
问题排查流程
- 快速定位 :使用
htop或top快速查看资源占用 - 详细分析 :使用
pidstat、pmap等工具深入分析 - 性能分析 :使用
perf、strace定位性能瓶颈 - 历史对比 :使用
sar查看历史数据,分析趋势 - 综合诊断:结合多个工具的结果,全面分析问题
定期监控和记录这些指标,有助于及时发现和解决性能问题。根据具体场景选择合适的工具组合,可以更高效地完成资源分析和问题排查。