进程是程序的执行实例,是操作系统资源分配的基本单位。

每个运行的程序在 Linux 中都是一个进程(具有独立的地址空间、代码段、堆、栈、数据段),包括 shell、nginx、mysqld、bash 等。

进程生命周期:

  1. 创建:通过 fork()、exec() 系列系统调用

  2. 就绪:等待内核调度

  3. 运行:CPU 调度运行中

  4. 阻塞:等待资源或事件(如 I/O)

  5. 终止:执行完毕或被杀死

  6. 僵尸:子进程结束但父进程未回收资源

进程状态

状态符含义说明
RRunning正在运行或可运行状态
SSleeping可中断的休眠
DUninterruptible不可中断(一般是 I/O 阻塞)
TStopped被暂停或调试
ZZombie僵尸状态,需父进程回收
XDead已终止(很少见)

ps

ps 命令(process status 的缩写)用于报告当前系统中运行的进程快照。它提供了关于正在运行的进程的信息,包括它们的 PID(进程 ID)、TTY(终端)、运行时间、CPU 使用情况以及命令名称等。

ps 的语法非常灵活,因为它有多种风格的选项:

  • UNIX 风格:以单破折号开头,如 ps -ef
  • BSD 风格:不带破折号,如 ps aux
  • GNU 风格:以双破折号开头,如 ps --forest

在实际使用中,通常会将不同风格的选项组合使用,这可能会导致一些混淆,但掌握一些常用的组合是关键。

核心功能与使用场景

ps 命令最常见的用途是查看进程列表。以下是一些核心的用法和它们的应用场景:

  1. 查看当前终端的进程:

    Bash

    1
    ps

    这是 ps 最简单的用法,它会显示当前与你的终端关联的进程。通常你会看到 bash(你的 shell)和 ps 命令本身。

  2. 查看所有进程(UNIX 风格):

    Bash

    1
    ps -ef
    • **-e**:选择所有进程。
    • **-f**:以“完整”格式显示列表,包括 UID、PID、PPID(父进程 ID)、C(CPU 使用率)、STIME(启动时间)、TTY、TIME(CPU 时间)和 CMD(命令)。

    这是在服务器运维中最常用的 ps 命令之一,因为它提供了详细且易读的进程信息。

  3. 查看所有进程(BSD 风格):

    1
    ps aux
    • **a**:显示所有终端上的进程(包括其他用户的)。
    • **u**:显示面向用户的格式(User-oriented format),包括 USER、PID、%CPU、%MEM、VSZ(虚拟内存大小)、RSS(常驻内存大小)、TTY、STAT(进程状态)、START(启动时间)、TIME 和 COMMAND。
    • **x**:显示没有控制终端的进程。

    ps aux 也是非常流行的一种用法,特别适合快速查看系统资源占用情况(%CPU, %MEM)。

选项解析与应用

ps 提供了大量的选项来定制输出。以下是一些在运维中非常有用的选项:

  • -o format 或 –format format: 自定义输出列。这是 ps 最强大的功能之一,允许你精确地选择想要的信息。

    例如,只显示 PID、进程名称和 CPU 使用率:

    1
    ps -eo pid,comm,%cpu

    常用的格式指定符包括:pid, ppid, user, group, comm (命令名), cmd (完整命令行), %cpu, %mem, vsz, rss, stat, tty, time, etime (运行时间)。

  • -p pid: 仅显示指定 PID 的进程。

    1
    ps -p 12345

    当你需要追踪特定进程的状态时非常有用。

  • -u userlist: 仅显示属于指定用户(或多个用户)的进程。

    1
    ps -u nginx,apache

    用于检查特定服务用户运行的进程,或排查某个用户引起的问题。

  • -C command: 仅显示指定命令名的进程。

    Bash

    1
    ps -C nginx

    用于查找所有 nginx 进程的实例,即使它们不是由同一个用户或在同一个 TTY 下运行。

  • -l: 显示长格式(long format)。提供了更多的技术细节,如进程优先级 (PRI)、nice 值 (NI) 等。

    Bash

    1
    ps -l
  • --forest: 以 ASCII 艺术图形式显示进程树。这对于理解进程之间的父子关系非常有帮助。

    1
    ps -ef --forest

    或者结合 aux 风格:

    Bash

    1
    ps aux --forest
  • grep 组合使用: ps 的输出通常很大,结合 grep 进行过滤是常见操作。

    例如,查找所有与 java 相关的进程:

    1
    ps -ef | grep java

    注意: 使用 grep 时,grep 命令本身也会出现在输出中。为了避免这种情况,可以使用 grep -v grep 或者更精确的正则表达式。

    1
    ps -ef | grep '[j]ava' # 避免匹配 grep 进程本身

进程状态(STAT)字段解析

ps 输出中的 STAT 字段非常重要,它指示了进程的当前状态:

  • R: Running 或 Runnable (正在运行或在运行队列中等待)。
  • S: Sleeping (可中断的睡眠状态,等待事件完成)。
  • D: Uninterruptible sleep (不可中断的睡眠状态,通常在等待 I/O 完成)。
  • Z: Zombie (僵尸进程,子进程已终止,但父进程尚未回收其资源)。
  • T: Stopped (被信号停止,如 SIGSTOPSIGTSTP)。
  • <: High-priority process (高优先级进程)。
  • N: Low-priority process (低优先级进程)。
  • L: Pages are locked into memory (内存页被锁定)。
  • s: Session leader (会话领导者)。
  • +: Foreground process group (前台进程组)。

实际应用场景

  1. 查找僵尸进程:

    1
    ps -ef | grep Z

    僵尸进程可能表明父进程没有正确处理子进程的退出,长时间累积可能耗尽系统资源。

  2. 找出 CPU 或内存占用最高的进程:

    1
    2
    ps aux --sort=-%cpu | head -n 5 # 按 CPU 降序排序,显示前5个
    ps aux --sort=-%mem | head -n 5 # 按内存降序排序,显示前5个

    这对于快速定位资源瓶颈非常有帮助。

  3. 检查特定服务的运行状态:

    1
    2
    ps -ef | grep nginx
    ps -ef | grep mysql

    确认服务是否正在运行,以及运行了多少个工作进程。

  4. 根据端口查找进程:

    这通常需要 lsof 或 netstat 的配合,但 ps 可以提供进程的详细信息:

    1
    lsof -i :80 | awk '{print $2}' | xargs ps -fp # 找出监听80端口的进程信息
  5. 查看守护进程(daemon):

    守护进程通常没有控制终端。

    1
    ps axj # 显示所有进程,包括没有控制终端的,并以作业控制格式显示

top/htop

kill

killall

nice/renice

jobs/fg/bg

nohup

pidof / pgrep

strace

lsof

systemctl / service