当前位置:首页>Linux>每天学一个Linux命令系列(23):ps - 找进程别再用ps -ef | grep了

每天学一个Linux命令系列(23):ps - 找进程别再用ps -ef | grep了

  • 2026-10-11 06:32:56
每天学一个Linux命令系列(23):ps - 找进程别再用ps -ef | grep了
运
运维少年 · 科技观察

这个命令是干啥的

ps = process status,就是"看当前有哪些进程在跑"。

刚学 Linux 的时候,找进程我就只会一招:

ps -ef | grep nginx

这招确实能用,但效率太低了。先 ps -ef 输出所有进程,再用 grep 过滤,如果机器上跑了几百个进程,输出会刷屏。而且 grep 自己也会出现在结果里(你要额外加 grep -v grep 排掉,挺烦的)。

ps 这个命令看起来简单,但它支持的选项多到能写一本书。关键是你要掌握几个高效用法,能快速找到你想要的信息。

基本用法(3分钟上手)

ps aux 是我最常用的

# 查看所有正在运行的进程
ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.4 169740 13540 ?        Ss   08:00   0:02 /sbin/init
root       789  0.1  1.2 523568 37512 ?        Ssl  08:01   0:15 /usr/bin/dockerd
www-data  1234  0.3  2.1 456890 65432 ?        S    08:05   0:45 nginx: worker process

各列含义:

  • ·USER:进程所属用户
  • ·PID:进程 ID
  • ·%CPU:CPU 占用百分比
  • ·%MEM:内存占用百分比
  • ·VSZ:虚拟内存大小(KB)
  • ·RSS:常驻物理内存大小(KB)
  • ·TTY:关联的终端,? 表示守护进程
  • ·STAT:进程状态(S=休眠, R=运行, D=不可中断, Z=僵尸)
  • ·START:启动时间
  • ·TIME:累计 CPU 时间
  • ·COMMAND:命令名

ps -ef 是标准输出

# 标准格式,PID 和 PPID(父进程 ID)比较清楚
ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:00 ?        00:00:02 /sbin/init
root       789     1  0 08:01 ?        00:00:15 /usr/bin/dockerd
  • ·-e:所有进程(同 -A)
  • ·-f:完整格式输出,显示 PPID 等信息

只看某个用户的进程

# 只看 mysql 用户的进程
ps -u mysql

# 或者看当前用户
ps -u $(whoami)
# 用 -U 也可以
ps -U nginx

找特定进程的 PID

# 用 -C 按命令名查找,不需要 grep
ps -C nginx
  PID TTY          TIME CMD
 1234 ?        00:00:45 nginx
 1235 ?        00:00:42 nginx

对比一下 ps -ef | grep nginx 的繁琐:

# 老办法:输出多,还要排掉 grep 自身
ps -ef | grep nginx | grep -v grep

# 新办法:干净利落
ps -C nginx

进阶骚操作

--sort:按 CPU 或内存排序

# 按 CPU 占用降序排列
ps aux --sort=-%cpu

# 按内存占用降序排列
ps aux --sort=-%mem

# 先按 CPU 排,再按内存排
ps aux --sort=-%cpu,-%mem

前面加 - 是降序,不加(或加 +)是升序。

这个功能省了我很多事。以前排查 CPU 飙高的问题,我得先 ps aux 刷一堆出来,再肉眼找。现在直接排好序,头几条就是罪魁祸首。

-o:自定义输出列

嫌 ps aux 出来的列太多?自己挑想要的:

# 只看 PID、CPU%、内存%、命令
ps -e -o pid,%cpu,%mem,cmd --sort=-%cpu | head -20
# 看你想看的任何列:RSS 物理内存,VSZ 虚拟内存,USER 用户
ps -eo pid,user,rss,vsz,%cpu,%mem,comm --sort=-%mem | head -10

常用列名:pid, ppid, user, rss, vsz, %cpu, %mem, comm(命令名,不带参数), cmd(带完整参数), etime(进程已运行时间), lstart(启动时间)。

# 找运行超过 24 小时的进程
ps -eo pid,etime,cmd --sort=etime | grep -E '^ +[0-9]+-[0-9]{2}:'

树形结构:ps axjf

进程的父子关系一目了然:

# 树形进程树
ps axjf
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0   0:02 /sbin/init
    1   789   789   789 ?           -1 Ssl      0   0:15  \_ /usr/bin/dockerd
  789  1298  1298  1298 ?           -1 Ssl      0   0:10      \_ containerd
    1   899   899   899 ?           -1 Ss       0   0:00  \_ /usr/sbin/sshd
  899  1500  1500  1500 ?           -1 Ss       0   0:00      \_ sshd: root@pts/0
 1500  1501  1501  1501 pts/0     1667 Ss       0   0:00          \_ -bash
 1501  1667  1667  1501 pts/0     1667 R+       0   0:00              \_ ps axjf

这比 pstree 还详细,能看到 PID 和用户。排查僵尸进程的时候特别有用,一眼看出哪个父进程没回收子进程。

结合 pgrep 用

# pgrep 只返回 PID 数字
pgrep -u nginx nginx

# 更简洁
pkill nginx   # 直接杀进程,比 kill $(pgrep nginx) 方便

显示子线程 -Lf

# 查看进程的线程
ps -Lf 1234

# 或者看所有线程
ps -eLf
# 找到 CPU 占用高的线程
ps -e -o pid,lwp,%cpu,%mem,comm --sort=-%cpu | head -10

LWP 列显示的是线程 ID(轻量级进程)。如果某个进程有多个线程,可以看到每个线程的 CPU 占用。这排查 Java 应用或 Python GIL 相关问题时必用。

避坑指南

1. ps aux 和 ps -ef 有什么区别

其实结果差不多,但列名不太一样:

ps auxps -ef意义
%CPUCCPU 占用率(aux 更直观)
VSZVSZ一致
RSSRSS一致
STATS进程状态
STARTSTIME启动时间

ps aux 更常用,ps -ef 是 POSIX 标准写法,两套都认得就行。

2. 别用 ps -ef | grep 找守护进程

守护进程(daemon)通常名字里有多个实例(比如 nginx 有 master 和 worker),grep 出来一堆:

# nginx 搜索出来可能有很多条
ps -ef | grep nginx
root  1200 ... nginx: master process /usr/sbin/nginx
www   1201 ... nginx: worker process
www   1202 ... nginx: worker process

用 -C 更方便:

# 只看 nginx 进程
ps -C nginx

3. 僵尸进程怎么排查

# 找带 Z 状态的进程
ps aux | grep ' Z '
# 更准确的方法
ps -eo pid,stat,comm | grep '^ *[0-9]\+ Z'

找到僵尸进程的父进程之后,再看父进程在干什么,一般是父进程没调用 wait()。如果父进程也被卡住了,可以考虑杀父进程释放子进程。

4. ps -ef 的输出被截断的问题

ps -ef 默认命令列只显示 80 个字符,长路径会被截断:

# 用 -ww 参数取消宽度限制
ps -efww

# 或者用 auxww
ps auxww

实战场景(重点!结合真实运维场景)

场景一:找到 CPU 最高进程

服务器报警说 CPU 超过了 90%,快速登录查:

# 直奔 CPU 最高的前 5 个进程
ps aux --sort=-%cpu | head -6
# 输出格式更清晰:只看 PID、CPU%、内存%、命令名
ps -eo pid,%cpu,%mem,args --sort=-%cpu | head -10

我遇到过一次 CPU 拉满,查出来是 PHP-FPM 的某个进程卡住了。看到某个 PID 的 CPU 一直 99%,直接重启就恢复了。

场景二:排查内存泄漏

# 按内存占用排序,检查 RES 列
ps aux --sort=-%mem | head -20
# 持续监控某进程的内存变化
watch -n 2 'ps -eo pid,rss,%mem,cmd --sort=-%mem | head -10'

内存泄漏的典型表现:%MEM 和 RSS 持续增长,不会降。如果某个进程两小时从 2% 涨到 20%,那大概率泄漏了。

场景三:看某个应用开了多少进程

# Nginx worker 数量
ps -C nginx --no-headers | wc -l

# MySQL 线程数
ps -C mysqld -o nlwp --no-headers

# 某个用户跑了多少进程
ps -u deploy -o pid --no-headers | wc -l

这些数据可以写到监控脚本里,配合 Prometheus 做指标采集。

场景四:杀掉所有子进程

# 找到父进程的所有子进程
ps --ppid 1234 -o pid --no-headers

# 组合成一行杀掉
kill $(ps --ppid 1234 -o pid --no-headers)

--ppid 参数按父进程 ID 过滤,非常实用。

场景五:定位 Java 应用线程问题

# 找到 Java 进程的 PID
ps -C java -o pid --no-headers

# 查看这个 Java 进程的所有线程
ps -Lf $(ps -C java -o pid --no-headers)
# 把 CPU 最高的线程转成十六进制(用于 jstack 匹配)
ps -eo pid,lwp,%cpu,comm --sort=-%cpu | head -5

# 线程 ID 转 16 进制
printf '%x\n' 12345

然后用 jstack 找到对应的线程栈,就知道代码卡在哪了。

今日作业(一道小题目)

题目:你的服务器突然变慢了,登录后发现 CPU 用了 98%,但不知道是哪个进程搞的。

要求:
1. 用一条 ps 命令找到 CPU 占用最高的 3 个进程
2. 输出只显示 PID、CPU 百分比、内存百分比、命令名
3. 按 CPU 降序排列
4. 同时再写一条命令,找到内存占用最高的 3 个进程(按内存降序)

写出这两条命令,并解释每条输出会看到什么。不限速。

E N D

运维少年 · 科技观察

最新文章

随机文章