跳转到内容

ps

ps(process status)用于查看进程状态。它拍的是一张快照,执行完就结束,不会刷新 —— 要持续观察用 htop。

Terminal window
ps [选项]

ps 有三套并存的选项风格:BSD 风格(不带 -,如 ps aux)、UNIX 风格(带 -,如 ps -ef)、GNU 长选项(带 --) 两种短风格的同名字母含义未必相同,ps aux 和 ps -aux 不是一回事,别混着写

ps 不问内核要数据,它读的是 /proc 下的伪文件系统:每个进程对应一个 /proc/<PID>/ 目录,status、stat、cmdline 这些文件里放着它的全部状态。

所以 ps 的输出是执行那一瞬间遍历 /proc 的结果,不同进程的数据严格来说也不在同一时刻。

BSD 风格,不加连字符:

选项 说明
a 显示所有用户的进程,不限于自己的
u 面向用户的格式,带 CPU、内存占用
x 包括没有控制终端的进程,也就是各种守护进程
f 以树状显示父子关系

UNIX 风格,加连字符:

选项 说明
-e 所有进程,等同 -A
-f 完整格式,带 PPID 和完整命令行
-l 长格式,带优先级、状态、WCHAN
-p <PID> 只看指定的进程
-u <用户> 只看指定用户的进程
-o <字段列表> 自定义输出哪些列
--sort <字段> 按字段排序,字段前加 - 为降序
--forest 树状显示

1. 两条最常用的

Terminal window
ps aux # BSD 风格,看资源占用
ps -ef # UNIX 风格,看进程关系

ps aux 的列:

列 含义
USER 属主
PID 进程号
%CPU CPU 占用百分比,是自进程启动以来的平均值,不是瞬时值
%MEM 占物理内存的百分比
VSZ 虚拟内存大小(KB),包含映射了但没真正用的部分
RSS 常驻内存大小(KB),真正占着的物理内存
TTY 控制终端,? 表示没有
STAT 进程状态
START 启动时刻
TIME 累计占用的 CPU 时间
COMMAND 命令行

判断一个进程占多少内存看 RSS,不看 VSZ

STAT 列的字母:

字母 含义
R 正在运行或在就绪队列里
S 可中断睡眠,等 IO 或事件,绝大多数进程平时都是这个
D 不可中断睡眠,通常卡在 IO 上,这种状态 kill -9 也杀不掉
T 已停止,Ctrl-Z 之后就是它
Z 僵尸,进程已经退出但父进程还没回收
< N 高优先级、低优先级
s + l 会话首进程、前台进程组、多线程

2. 自定义列并排序

Terminal window
ps -eo pid,ppid,user,%mem,rss,comm --sort=-%mem | head

-o 只取关心的列,输出窄了才好读 --sort=-%mem 按内存降序,找吃内存的进程

3. 找特定的进程

Terminal window
ps -ef | grep nginx
pgrep -a nginx

ps | grep 会把 grep 自己也匹配进去,得再加一层 grep -v grep pgrep 没这个问题,-a 让它连命令行一起输出

4. 看进程树

Terminal window
ps -ef --forest
ps auxf

排查「这个进程是谁拉起来的」时比平铺列表直观得多

5. 找僵尸进程

Terminal window
ps -eo pid,ppid,stat,comm | awk '$3 ~ /^Z/'

僵尸进程只占一个进程表项,不占 CPU 和内存,也杀不掉 —— 它已经死了 要清掉得让父进程去回收,或者杀掉父进程,让 init 接管后代为回收

  • man ps
  • man 5 proc(/proc/<PID>/ 下各个文件的格式)