一、ps 命令概述
1.1 什么是 ps 命令
ps(Process Status)是 Linux/Unix 系统中最基础也是最重要的进程查看工具之一。它用于显示当前系统中运行的进程快照信息,包括进程 ID、用户、CPU 使用率、内存占用等关键指标。
核心特点:
- 静态快照:ps 显示的是执行命令瞬间的进程状态,而非实时更新(与 top 命令不同)
- 信息丰富:可以显示进程的几乎所有属性信息
- 灵活过滤:支持多种选项组合,精确定位目标进程
1.2 ps 命令的两种语法风格
ps 命令支持三种不同的选项风格,这是历史原因造成的:
bash
# 1. UNIX 风格(单破折号)
ps -ef
ps -aux
# 2. BSD 风格(无破折号)
ps aux
ps axjf
# 3. GNU 长选项风格(双破折号)
ps --forest
ps --sort=-pcpu
重要提示: 不同风格不能混用!ps -aux 和 ps aux 虽然看起来相似,但含义完全不同:
ps aux(BSD 风格):显示所有用户的所有进程ps -aux(UNIX 风格):-a显示所有终端进程,u被解释为用户名,x显示无终端进程
二、常用选项详解
2.1 最常用的两种组合
2.1.1 ps -ef(UNIX 风格)
bash
ps -ef
选项说明:
-e:显示所有进程(every process)-f:完整格式输出(full format)
输出字段解析:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Oct17 ? 00:46:40 /usr/lib/systemd/systemd --switched-root --system
root 2 0 0 Oct17 ? 00:00:00 [kthreadd]
root 3 2 0 Oct17 ? 00:00:00 [pool_workqueue_release]
| 字段 | 含义 | 详细说明 |
|---|---|---|
| UID | 用户 ID | 进程所有者的用户名或 UID |
| PID | 进程 ID | 进程的唯一标识符(Process ID) |
| PPID | 父进程 ID | 创建该进程的父进程 ID(Parent PID) |
| C | CPU 使用率 | CPU 利用率的整数值 |
| STIME | 启动时间 | 进程启动的时间 |
| TTY | 终端 | 进程关联的终端(? 表示无终端) |
| TIME | CPU 时间 | 进程累计占用的 CPU 时间 |
| CMD | 命令 | 启动进程的完整命令行 |
2.1.2 ps aux(BSD 风格)
bash
ps aux
选项说明:
a:显示所有终端下的进程u:以用户为主的格式显示x:显示没有控制终端的进程
输出字段解析:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 125684 4096 ? Ss Oct17 0:46 /usr/lib/systemd/systemd
| 字段 | 含义 | 详细说明 |
|---|---|---|
| USER | 用户名 | 进程所有者 |
| PID | 进程 ID | 同上 |
| %CPU | CPU 百分比 | 进程占用 CPU 的百分比 |
| %MEM | 内存百分比 | 进程占用物理内存的百分比 |
| VSZ | 虚拟内存 | 进程使用的虚拟内存大小(KB) |
| RSS | 常驻内存 | 进程实际使用的物理内存(KB) |
| TTY | 终端 | 同上 |
| STAT | 进程状态 | 进程当前状态(详见下文) |
| START | 启动时间 | 进程启动时间 |
| TIME | CPU 时间 | 累计 CPU 时间 |
| COMMAND | 命令 | 完整命令行 |
2.2 进程状态码(STAT)详解
STAT 字段是理解进程状态的关键,常见状态码:
| 状态码 | 含义 | 说明 |
|---|---|---|
| R | Running | 正在运行或可运行(在运行队列中) |
| S | Sleeping | 可中断睡眠(等待事件完成) |
| D | Disk Sleep | 不可中断睡眠(通常是 I/O 操作) |
| Z | Zombie | 僵尸进程(已终止但未被父进程回收) |
| T | Stopped | 已停止(收到 SIGSTOP 信号) |
| I | Idle | 空闲内核线程 |
| < | 高优先级 | 进程优先级高于正常值 |
| N | 低优先级 | 进程优先级低于正常值 |
| L | 有锁页 | 有页面锁定在内存中 |
| s | 会话领导 | 进程是会话领导者 |
| l | 多线程 | 进程是多线程的 |
| + | 前台进程 | 进程在前台进程组 |
示例:
Ss:可中断睡眠且是会话领导者R+:正在运行的前台进程Ssl:可中断睡眠、会话领导者、多线程
2.3 其他实用选项
bash
# 显示进程树(树状结构)
ps -ef --forest
ps axjf
# 显示线程信息
ps -eLf # 显示所有线程
ps -T -p PID # 显示指定进程的线程
# 自定义输出格式
ps -eo pid,ppid,cmd,pcpu,pmem,stat
# 按 CPU 使用率排序
ps aux --sort=-pcpu
# 按内存使用率排序
ps aux --sort=-pmem
# 显示指定用户的进程
ps -u username
ps -U username
# 显示指定进程 ID
ps -p 1234
ps -p 1234,5678,9012
# 显示指定命令的进程
ps -C nginx
三、实战技巧
3.1 查找特定进程
方法一:使用 grep 过滤
bash
# 查找 nginx 进程
ps -ef | grep nginx
# 排除 grep 自身
ps -ef | grep nginx | grep -v grep
# 更优雅的方式(使用正则表达式)
ps -ef | grep [n]ginx
方法二:使用 pgrep
bash
# 更简洁的方式
pgrep -l nginx
# 显示完整命令
pgrep -a nginx
# 显示进程树
pgrep -a nginx | xargs ps -p
方法三:使用 ps 自带过滤
bash
# 按命令名过滤
ps -C nginx -o pid,cmd
# 按进程 ID 过滤
ps -p $(pgrep nginx) -o pid,ppid,cmd
3.2 监控资源占用
查找 CPU 占用最高的 10 个进程:
bash
ps aux --sort=-pcpu | head -n 11
查找内存占用最高的 10 个进程:
bash
ps aux --sort=-pmem | head -n 11
查看指定进程的资源占用:
bash
# 持续监控(配合 watch)
watch -n 1 'ps -p 1234 -o pid,pcpu,pmem,vsz,rss,cmd'
# 查看详细内存信息
ps -p 1234 -o pid,vsz,rss,sz,cmd
3.3 进程树分析
显示完整进程树:
bash
# 方法一:使用 --forest
ps -ef --forest
# 方法二:使用 BSD 风格
ps axjf
# 方法三:使用 pstree(更直观)
pstree -p # 显示 PID
pstree -a # 显示命令行参数
pstree -p PID # 显示指定进程的子树
查找进程的父子关系:
bash
# 查找指定进程的所有子进程
ps --ppid 1234
# 查找进程的父进程
ps -p 1234 -o ppid=
3.4 自定义输出格式
ps 支持高度自定义的输出格式,使用 -o 选项:
bash
# 基本格式
ps -eo pid,ppid,user,cmd
# 完整资源信息
ps -eo pid,ppid,user,%cpu,%mem,vsz,rss,stat,start,time,cmd
# 添加表头
ps -eo pid,cmd --no-headers # 无表头
ps -eo pid,cmd # 有表头(默认)
# 指定列宽
ps -eo pid:6,user:10,cmd:50
常用输出字段:
pid - 进程 ID
ppid - 父进程 ID
pgid - 进程组 ID
sid - 会话 ID
user - 用户名
uid - 用户 ID
group - 组名
gid - 组 ID
%cpu - CPU 使用率
%mem - 内存使用率
vsz - 虚拟内存大小
rss - 物理内存大小
sz - 物理页面大小
tty - 终端
stat - 进程状态
start - 启动时间
time - CPU 时间
etime - 运行时长
nice - 优先级
pri - 优先级(内核视角)
pcpu - CPU 使用率
pmem - 内存使用率
cmd - 命令
comm - 命令名(不含参数)
args - 完整命令行
3.5 实用脚本示例
监控特定服务的资源占用:
bash
#!/bin/bash
# monitor_service.sh
SERVICE="nginx"
while true; do
clear
echo "=== $SERVICE 进程监控 ==="
echo "时间: $(date)"
echo ""
ps aux | grep $SERVICE | grep -v grep | \
awk '{printf "PID: %-6s CPU: %-5s MEM: %-5s CMD: %s\n", $2, $3"%", $4"%", $11}'
sleep 2
done
检查僵尸进程:
bash
#!/bin/bash
# check_zombie.sh
ZOMBIE_COUNT=$(ps aux | awk '$8=="Z" {print $0}' | wc -l)
if [ $ZOMBIE_COUNT -gt 0 ]; then
echo "发现 $ZOMBIE_COUNT 个僵尸进程:"
ps aux | awk '$8=="Z" {print "PID: " $2 " PPID: " $3 " CMD: " $11}'
# 获取父进程信息
echo ""
echo "父进程信息:"
ps aux | awk '$8=="Z" {print $3}' | sort -u | while read ppid; do
ps -p $ppid -o pid,user,cmd
done
else
echo "没有发现僵尸进程"
fi
生成进程报告:
bash
#!/bin/bash
# process_report.sh
OUTPUT="process_report_$(date +%Y%m%d_%H%M%S).txt"
{
echo "========================================="
echo "进程状态报告"
echo "生成时间: $(date)"
echo "========================================="
echo ""
echo "1. 进程总数:"
ps aux | wc -l
echo ""
echo "2. CPU 占用 Top 10:"
ps aux --sort=-pcpu | head -n 11
echo ""
echo "3. 内存占用 Top 10:"
ps aux --sort=-pmem | head -n 11
echo ""
echo "4. 进程状态统计:"
ps aux | awk 'NR>1 {print $8}' | sed 's/^\(.\).*/\1/' | sort | uniq -c
echo ""
echo "5. 用户进程分布:"
ps aux | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn
} > $OUTPUT
echo "报告已生成: $OUTPUT"
四、ps 与其他命令的配合
4.1 ps + grep(进程过滤)
bash
# 基础用法
ps -ef | grep nginx
# 排除 grep 自身(方法一)
ps -ef | grep nginx | grep -v grep
# 排除 grep 自身(方法二,推荐)
ps -ef | grep [n]ginx
# 统计进程数量
ps -ef | grep nginx | grep -v grep | wc -l
# 提取 PID
ps -ef | grep nginx | grep -v grep | awk '{print $2}'
4.2 ps + awk(数据处理)
bash
# 提取特定列
ps aux | awk '{print $2, $11}'
# 过滤高 CPU 占用进程
ps aux | awk '$3 > 50 {print $0}'
# 过滤高内存占用进程
ps aux | awk '$4 > 10 {print $2, $4, $11}'
# 统计各状态进程数量
ps aux | awk 'NR>1 {count[$8]++} END {for (state in count) print state, count[state]}'
# 计算总内存占用
ps aux | awk '{sum+=$6} END {print "Total RSS: " sum/1024 " MB"}'
4.3 ps + xargs(批量操作)
bash
# 批量 kill 进程
ps -ef | grep defunct | grep -v grep | awk '{print $2}' | xargs kill -9
# 批量查看进程详情
pgrep nginx | xargs ps -o pid,ppid,cmd -p
# 批量检查进程状态
ps -ef | grep python | awk '{print $2}' | xargs -I {} sh -c 'echo "PID: {}"; ls -l /proc/{}/fd | wc -l'
4.4 ps + watch(实时监控)
bash
# 实时监控所有进程
watch -n 1 'ps aux --sort=-pcpu | head -n 20'
# 监控特定进程
watch -n 1 'ps -ef | grep nginx'
# 监控进程数量变化
watch -n 1 'ps aux | wc -l'
五、常见问题与解决方案
5.1 ps -ef 与 ps aux 的区别
核心区别:
| 特性 | ps -ef | ps aux |
|---|---|---|
| 风格 | UNIX System V | BSD |
| 显示内容 | 所有进程完整信息 | 所有进程详细状态 |
| CPU/内存 | 显示 C(CPU 利用率整数) | 显示 %CPU、%MEM(百分比) |
| 内存信息 | 不显示 | 显示 VSZ、RSS |
| 进程状态 | 不直接显示 | 显示 STAT 字段 |
| 命令显示 | 完整命令路径 | 完整命令行参数 |
选择建议:
- 需要查看进程层级关系:优先使用
ps -ef --forest - 需要查看资源占用:优先使用
ps aux - 需要快速定位进程:两者都可以,根据习惯选择
- 脚本中使用:建议统一使用一种风格,避免混淆
5.2 如何处理僵尸进程
识别僵尸进程:
bash
# 方法一
ps aux | grep Z | grep -v grep
# 方法二
ps aux | awk '$8=="Z" || $8=="Z+" {print $0}'
# 方法三(更精确)
ps -eo pid,ppid,stat,cmd | grep '^[0-9].*Z'
处理方法:
bash
# 1. 找到僵尸进程的父进程
ps -o ppid= -p <僵尸进程PID>
# 2. 向父进程发送 SIGCHLD 信号(让父进程回收子进程)
kill -SIGCHLD <父进程PID>
# 3. 如果父进程不响应,重启父进程
kill -HUP <父进程PID>
# 4. 最后手段:杀死父进程(谨慎使用)
kill -9 <父进程PID>
预防措施:
- 确保程序正确使用
wait()或waitpid()回收子进程 - 设置 SIGCHLD 信号处理器
- 使用双重 fork 技巧避免僵尸进程
5.3 VSZ 与 RSS 的区别
VSZ(Virtual Size):
- 虚拟内存大小,包括所有映射的内存
- 包含:进程代码、数据、共享库、交换空间等
- 可能远大于实际物理内存
- 不代表真实内存占用
RSS(Resident Set Size):
- 常驻内存大小,进程实际占用的物理内存
- 不包括已交换到 swap 的内存
- 包括共享库占用的内存(可能重复计算)
- 更接近真实内存占用
示例对比:
bash
# 查看特定进程的内存详情
ps -o pid,vsz,rss,pmem,cmd -p 1234
# 更详细的内存分析(需要 root 权限)
cat /proc/1234/status | grep -E 'VmSize|VmRSS|VmSwap'
# 使用 smem 获取更准确的内存占用(考虑共享内存)
smem -p | grep process_name
5.4 为什么 ps 看不到某些进程
可能原因:
- 权限不足:
bash
# 只能看到当前用户的进程
ps -u $(whoami)
# 需要 root 权限查看所有进程
sudo ps -ef
- 进程已退出:
bash
# ps 是静态快照,进程可能已结束
# 使用 top 或 htop 实时监控
- 内核线程:
bash
# 某些选项不显示内核线程
ps -ef # 显示内核线程(命令在 [] 中)
ps aux # 也显示内核线程
- 命令名被截断:
bash
# 使用 -w 选项避免截断
ps auxw
ps auxww # 无限宽度
5.5 高 CPU 但 top 看不到
如果 ps 显示进程 CPU 高,但 top 中看不到:
bash
# 1. ps 显示的是累计 CPU 时间,top 显示的是实时 CPU 占用
ps -eo pid,etime,time,pcpu,cmd --sort=-time
# 2. 可能是短时间高 CPU 爆发
# 使用 pidstat 监控(需要安装 sysstat)
pidstat 1
# 3. 可能是多线程进程
ps -eLf | grep process_name
top -H -p PID # 显示线程级别的 CPU 占用
六、性能优化建议
6.1 大规模进程场景优化
场景:系统有数千个进程时,ps 命令可能很慢
bash
# 避免使用 grep 多次扫描
# 不推荐
ps aux | grep nginx | grep -v grep | awk '{print $2}'
# 推荐
ps aux | awk '/nginx/ && !/awk/ {print $2}'
# 使用更精确的过滤
ps -C nginx -o pid= # 直接按命令名过滤
# 减少输出字段
ps -eo pid,cmd | grep nginx # 只输出需要的字段
6.2 脚本中的最佳实践
bash
#!/bin/bash
# 1. 避免使用 grep | grep -v grep
# 不推荐
PIDS=$(ps -ef | grep nginx | grep -v grep | awk '{print $2}')
# 推荐方法一:使用 pgrep
PIDS=$(pgrep nginx)
# 推荐方法二:使用正则技巧
PIDS=$(ps -ef | grep [n]ginx | awk '{print $2}')
# 推荐方法三:使用 awk
PIDS=$(ps -ef | awk '/nginx/ && !/awk/ {print $2}')
# 2. 使用 --no-headers 避免处理表头
ps aux --no-headers | awk '$3 > 50 {print $2}'
# 3. 精确指定输出格式
ps -eo pid,cmd= --no-headers | grep nginx
# 4. 设置列宽避免截断
ps -eo pid:10,cmd:100 --no-headers
6.3 减少资源消耗
bash
# 1. 只查询需要的进程
ps -p 1234 # 指定 PID
ps -u nginx # 指定用户
ps -C nginx # 指定命令名
# 2. 限制输出字段
ps -eo pid,cmd # 只输出 PID 和命令
# 3. 使用更轻量的工具
pidof nginx # 只获取 PID
pgrep -l nginx # 轻量级进程查找
七、进阶技巧
7.1 按多个条件排序
bash
# 先按 CPU 排序,再按内存排序
ps aux --sort=-pcpu,-pmem
# 先按用户排序,再按 CPU 排序
ps aux --sort=user,-pcpu
# 可用的排序键
# pcpu, pmem, pid, ppid, user, time, etime, size, rss, vsz
7.2 显示进程的环境变量
bash
# 显示指定进程的环境变量
ps eww -p 1234
# 或者直接查看 /proc
cat /proc/1234/environ | tr '\0' '\n'
7.3 查看进程打开的文件
bash
# 结合 lsof
ps -ef | grep nginx | awk '{print $2}' | xargs -I {} lsof -p {}
# 查看进程的文件描述符
ls -l /proc/$(pgrep nginx)/fd
7.4 监控进程生命周期
bash
#!/bin/bash
# watch_process_lifecycle.sh
PROCESS_NAME="nginx"
LOG_FILE="process_lifecycle.log"
while true; do
CURRENT=$(ps -eo pid,etime,cmd | grep $PROCESS_NAME | grep -v grep)
if [ ! -z "$CURRENT" ]; then
echo "[$(date)] 进程运行中: $CURRENT" >> $LOG_FILE
else
echo "[$(date)] 进程未运行" >> $LOG_FILE
fi
sleep 5
done
7.5 分析进程 CPU 亲和性
bash
# 查看进程绑定的 CPU 核心
ps -eo pid,psr,comm | grep nginx
# PSR 字段表示进程当前运行的 CPU 核心编号
# 设置 CPU 亲和性
taskset -p PID # 查看
taskset -cp 0,1 PID # 绑定到 CPU 0 和 1
八、总结与最佳实践
8.1 核心要点
-
选择合适的选项组合:
- 日常使用:
ps aux或ps -ef - 资源监控:
ps aux --sort=-pcpu - 进程树分析:
ps -ef --forest - 精确过滤:
ps -C command_name
- 日常使用:
-
理解输出字段:
- CPU:区分累计时间(TIME)和占用率(%CPU)
- 内存:区分虚拟内存(VSZ)和物理内存(RSS)
- 状态:重点关注 Z(僵尸)、D(不可中断)、R(运行)
-
正确使用过滤:
- 优先使用
ps -C、pgrep而非grep - 避免
grep | grep -v grep模式 - 使用
awk进行复杂过滤
- 优先使用
8.2 常用命令速查
bash
# 查看所有进程
ps -ef
ps aux
# 查看进程树
ps -ef --forest
ps axjf
# 资源排序
ps aux --sort=-pcpu | head -20 # CPU Top 20
ps aux --sort=-pmem | head -20 # 内存 Top 20
# 查找特定进程
ps -C nginx
pgrep -a nginx
ps -ef | grep [n]ginx
# 自定义输出
ps -eo pid,user,%cpu,%mem,cmd
# 监控特定进程
watch -n 1 'ps -p 1234 -o pid,pcpu,pmem,cmd'
# 查看线程
ps -eLf
ps -T -p PID
# 检查僵尸进程
ps aux | awk '$8=="Z"'
8.3 故障排查检查清单
当系统出现性能问题时,按以下顺序检查:
bash
# 1. 检查整体进程状态
ps aux | head -20
# 2. 查找高 CPU 占用进程
ps aux --sort=-pcpu | head -10
# 3. 查找高内存占用进程
ps aux --sort=-pmem | head -10
# 4. 检查僵尸进程
ps aux | awk '$8=="Z" || $8=="Z+"'
# 5. 检查 D 状态进程(可能等待 I/O)
ps aux | awk '$8=="D" || $8~/^D/'
# 6. 统计进程数
ps aux | wc -l
# 7. 按用户统计
ps aux | awk 'NR>1 {count[$1]++} END {for (u in count) print u, count[u]}'
# 8. 检查长时间运行的进程
ps -eo pid,etime,cmd --sort=-etime | head -10
8.4 安全注意事项
-
敏感信息泄露:
ps可以看到完整命令行,包括密码等参数- 避免在命令行传递敏感信息
- 使用配置文件或环境变量替代
-
权限控制:
- 普通用户只能看到自己的进程详细信息
- 其他用户的进程只能看到部分信息
- 系统管理需要 root 权限
-
资源消耗:
- 在高负载系统中频繁执行
ps可能影响性能 - 使用
nice或ionice降低优先级 - 考虑使用缓存或采样机制
- 在高负载系统中频繁执行
8.5 延伸学习
相关命令:
top/htop:实时进程监控pgrep/pkill:进程查找与管理pstree:进程树可视化pidstat:进程统计(sysstat 包)/proc文件系统:进程详细信息
推荐阅读:
man ps:完整的 ps 命令手册man proc:/proc 文件系统详解- Linux 内核文档:进程管理章节
九、参考案例
案例 1:排查 CPU 占用异常
bash
# 1. 查找高 CPU 进程
ps aux --sort=-pcpu | head -5
# 2. 查看进程线程
ps -T -p <PID>
# 3. 查看进程调用栈
pstack <PID>
# 4. 使用 strace 跟踪系统调用
strace -p <PID> -c -f
案例 2:内存泄漏分析
bash
# 1. 持续监控进程内存
watch -n 5 'ps -p <PID> -o pid,vsz,rss,%mem,cmd'
# 2. 查看详细内存映射
cat /proc/<PID>/smaps
# 3. 使用 valgrind 检测内存泄漏(开发环境)
valgrind --leak-check=full ./your_program
案例 3:批量管理服务进程
bash
#!/bin/bash
# manage_service.sh
SERVICE="nginx"
ACTION=$1
case $ACTION in
status)
ps -C $SERVICE -o pid,ppid,%cpu,%mem,cmd
;;
count)
ps -C $SERVICE --no-headers | wc -l
;;
kill)
ps -C $SERVICE -o pid= | xargs kill -15
;;
force-kill)
ps -C $SERVICE -o pid= | xargs kill -9
;;
*)
echo "Usage: $0 {status|count|kill|force-kill}"
;;
esac