排查一台机器「现在在干什么」的入门四件套:ps 看进程快照、top 看实时负载、uname 看内核信息、who 看谁登录着。

ps

ps - 查看当前系统的进程快照(某一时刻的静态列表,区别于 top 的实时刷新)

常用命令

  • ps aux BSD 风格列出所有进程,含 CPU / 内存占用、启动时间、完整命令
  • ps -ef System V 风格列出所有进程,含 PPID(父进程 ID),适合看进程父子关系
  • ps aux | grep java 查找包含 java 的进程(grep 自身也会出现在结果里,可写成 grep [j]ava 排除)
  • pgrep -f "spring-boot" 直接按命令行匹配取 PID,比 ps | grep 更干净
  • ps aux --sort=-%mem | head -11 按内存占用降序取前 10(首行为表头)
  • ps aux --sort=-%cpu | head -11 按 CPU 占用降序取前 10
  • ps -ef --forest 以树状缩进展示进程父子层级
  • ps -p 1234 -o pid,ppid,user,%cpu,%mem,etime,cmd 查看指定进程的自定义字段,etime 为已运行时长
  • ps -u nginx -o pid,%cpu,%mem,cmd 查看某用户的所有进程
  • ps -eLf | grep 1234 查看某进程的所有线程(LWP 列即线程 ID)
  • ps aux | awk '$8 ~ /^Z/ {print $2, $11}' 找出僵尸进程(STAT 为 Z)
  • ps -o etime= -p 1234 只输出某进程已运行时长(无表头),适合脚本使用

语法格式

ps [options]

# 三种风格可混用但易混淆:
#   UNIX/System V 风格:带单横线,如 ps -ef
#   BSD 风格:不带横线,如 ps aux
#   GNU 长选项:双横线,如 ps --sort、--forest

OPTIONS

  • a 显示所有终端上的进程(含其他用户)
  • u 面向用户的输出格式(显示 USER、%CPU、%MEM 等)
  • x 包含没有控制终端的进程(守护进程)
  • -e 显示所有进程(等价于 -A
  • -f 完整格式输出,含 UID、PPID、STIME
  • -p pid 按 PID 过滤,可逗号分隔多个
  • -u user 按用户过滤(注意与 BSD 的 u 含义不同)
  • -o format 自定义输出列,如 -o pid,ppid,%cpu,%mem,etime,cmd
  • --sort=[+-]key 按字段排序,- 为降序,如 --sort=-%mem
  • -L 显示线程(LWP / NLWP 列)

备注

  • ps auxps -aux 不同:带横线的 -u 是"按用户过滤",Linux 下 ps -aux 会先尝试找名为 x 的用户,找不到时才降级为 ps aux 并给出警告
  • macOS/BSD 的 ps 不支持 --sort--forest 等 GNU 长选项,排序需用管道:ps aux | sort -k3 -nr | head(k3 为 CPU、k4 为内存);看进程树可另装 pstree
  • %CPU 是进程整个生命周期的平均占用而非瞬时值,长期运行的进程该值可能明显偏低,看瞬时占用应改用 top

top

top - 实时动态显示系统整体运行状态与各进程的资源占用情况

常用命令

  • top 启动实时监控界面,默认按 CPU 占用降序刷新
  • top -d 2 设置刷新间隔为 2 秒(默认 3 秒)
  • top -p 1234 只监控 PID 为 1234 的进程,可逗号指定多个:top -p 1234,5678
  • top -u nginx 只显示 nginx 用户的进程
  • top -b -n 1 > top.log 批处理模式采样 1 次并输出到文件,适合脚本采集
  • top -H -p 1234 以线程视角查看某进程内各线程的资源占用(排查 Java 高 CPU 线程常用)
  • top -c 显示完整命令行(含参数),而非只显示程序名
  • top -o %MEM 启动时直接按内存占用排序

交互快捷键(进入 top 后按键生效)

  • P 按 CPU 占用排序(默认)
  • M 按内存占用排序
  • T 按累计 CPU 时间排序
  • 1 展开/收起每个 CPU 核心的独立使用率
  • k 杀进程:先输入 PID,再输入信号(默认 15,强杀输入 9)
  • r renice:调整指定进程的优先级
  • c 切换显示完整命令行
  • H 切换线程视图
  • u 按用户过滤
  • z / x / y 彩色显示 / 高亮排序列 / 高亮运行中任务
  • W 保存当前配置到 ~/.toprc,下次启动沿用
  • q 退出

语法格式

top [-hv] [-bcHiOSs] [-d secs] [-n max] [-u|U user] [-p pid[,pid...]] [-o field] [-w [cols]]

OPTIONS

  • -d secs 刷新间隔秒数,支持小数如 -d 0.5
  • -n max 刷新指定次数后自动退出,常与 -b 配合
  • -b 批处理模式,输出纯文本,不进入交互界面
  • -p pid 只监控指定 PID,可多次指定或逗号分隔
  • -u user 只显示指定用户的进程
  • -H 显示线程而非进程
  • -c 显示完整命令行
  • -o field 按指定字段排序,如 %CPU%MEM
  • -i 不显示空闲(idle)进程

备注

  • macOS 自带的 top 是 BSD 版本,选项差别很大:排序用 -o cpu / -o mem(小写、无 %),刷新间隔是 -s 而非 -d,也没有 1 展开多核等交互键;Linux 上的说明不能直接套用
  • htop 是更友好的现代替代品:支持鼠标操作、横向查看完整命令、树状视图(F5)、直接搜索过滤(F3/F4),大多数发行版 apt/yum install htop 即可
  • 内存列注意区分 VIRT(虚拟内存,通常虚高)、RES(实际占用物理内存,看这个)、SHR(共享内存);判断进程真实内存占用应看 RES

uname

uname - 显示当前系统的内核与硬件架构信息

常用命令

  • uname -a 一次性输出全部信息:内核名、主机名、内核版本、硬件架构等
  • uname -r 显示内核 release 版本(如 5.15.0-105-generic),排障、装驱动、匹配内核模块最常用
  • uname -m 显示硬件架构(x86_64 / aarch64 / arm64),下载二进制包前先确认
  • uname -s 显示内核名称(Linux / Darwin),脚本中判断操作系统类型的标准写法
  • uname -n 显示主机名(等价于 hostname
  • case "$(uname -s)" in Linux) ... ;; Darwin) ... ;; esac shell 脚本中区分 Linux 与 macOS 的惯用法
  • uname -sr 组合输出内核名与版本(选项可任意组合)
  • cat /etc/os-release 查看发行版名称与版本(uname 只反映内核,不含发行版信息,二者配合使用)

语法格式

uname [OPTION]...

OPTIONS

  • -a, --all 按固定顺序输出以下全部信息
  • -s, --kernel-name 内核名称(默认行为,不带任何参数时即输出此项)
  • -n, --nodename 网络主机名
  • -r, --kernel-release 内核 release 版本号
  • -v, --kernel-version 内核构建版本与编译时间
  • -m, --machine 硬件架构名称
  • -p, --processor 处理器类型(Linux 上常显示 unknown)
  • -i, --hardware-platform 硬件平台(Linux 上常显示 unknown)
  • -o, --operating-system 操作系统名称(如 GNU/Linux)

备注

  • uname 只描述内核,查发行版应看 /etc/os-release(或 lsb_release -a),例如 Ubuntu 22.04 与 CentOS 都可能跑相同大版本内核
  • macOS 上 uname -s 输出 Darwin,Apple Silicon 的 uname -m 输出 arm64(Linux ARM64 则是 aarch64),跨平台脚本判断架构时两种写法都要兼容;macOS 的 BSD uname 不支持 -i-o 等 GNU 选项
  • Rosetta 2 下运行 x86_64 终端时 uname -m 会报 x86_64,与真实芯片架构不符,可用 sysctl -n machdep.cpu.brand_string 核实

who

who - 显示当前登录到系统的用户信息(来源于 /var/run/utmp 记录)

常用命令

  • who 列出当前所有登录用户:用户名、终端、登录时间、来源 IP
  • who -H 带表头输出,各列含义一目了然
  • whoami 显示当前有效用户名(su / sudo 切换后显示的是切换后的身份)
  • who am i 显示当前终端对应的登录用户(su 切换后仍显示最初登录者),等价于 who -m
  • who -b 显示系统最近一次启动时间
  • who -r 显示当前 runlevel(systemd 系统上对应 target)
  • who -q 只输出登录用户名列表和总数,快速统计在线人数
  • who -u 附带显示每个会话的空闲时长和进程 PID,识别挂机会话
  • w 比 who 更详细:额外显示系统负载、每个用户正在执行的命令
  • last | head -20 查看最近的登录历史(读取 /var/log/wtmp,与 who 互补)

语法格式

who [OPTION]... [FILE | ARG1 ARG2]

OPTIONS

  • -a 显示全部信息,相当于 -b -d -p -r -t -T -u 的合集
  • -b 显示系统最近一次启动时间
  • -H 输出列标题
  • -m 只显示与当前终端关联的用户(同 who am i
  • -q 只列用户名和登录总数
  • -r 显示当前 runlevel
  • -u 显示空闲时长(IDLE)与登录进程 PID
  • -d 显示已死亡的进程记录
  • -T 显示用户消息状态(+ 可接收 write 消息,- 不可,? 未知)

备注

  • who am iwhoami 容易混淆:前者回答"我是从哪个终端、以谁的身份登录的"(su 后不变),后者回答"我现在的有效用户是谁"(su 后改变)
  • 排障时三件套搭配用:who 看当前在线、w 看在线用户在干什么、last 看历史登录与重启记录(last reboot 专看重启历史)
  • 在部分容器或 tmux/screen 环境中 utmp 记录不完整,who 可能输出为空,不代表无人登录