Linux运维进阶技巧-进程分析与管理
查看进程信息
ps命令
ps命令是用于显示系统中当前运行的进程信息,是进行系统监控与性能调优的基础工具之一。
ps使用语法:
ps 选项
ps选项风格分为以下三种:
- BSD风格:用法特点就是选项不加破折号
-,比如:ps aux。 - Unix风格:用法特点就是选项需要加单破折号
-,比如:ps -elf。 - GNU风格:用法特点就是选项使用双破折号
--,比如:ps --sort。
常用选项说明:
a:显示所有终端上的进程(包括其他用户)u:显示进程的详细信息(用户、CPU、内存占用等)x:显示没有控制终端的进程(如守护进程)r:仅显示正在运行的进程T:显示当前终端的所有进程-e:显示所有进程(等价于 -A)-A:显示所有进程-f:显示完整格式(包括 PPID、CMD 参数等)-l:使用长格式显示-u <用户>:显示指定用户的进程-p <PID>:指定进程ID-t <终端>:显示指定终端的进程-C <命令>:显示指定命令名的进程-o <格式>:自定义输出字段--sort <字段>:指定排序字段--forest:以树状结构显示父子关系
1.ps aux
【示例】
ps aux
选项说明:
a: 显示终端上的所有进程,包括其他用户的进程u: 表示列出进程的用户x: 显示所有终端的进程
查看结果如下所示:
root@ihavetwocats:~# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.2 167816 10180 ? Ss May08 262:44 /sbin/init
root 2 0.0 0.0 0 0 ? S May08 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< May08 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< May08 0:00 [rcu_par_gp]
root 5 0.0 0.0 0 0 ? I< May08 0:00 [slub_flushwq]
root 6 0.0 0.0 0 0 ? I< May08 0:00 [netns]
root 8 0.0 0.0 0 0 ? I< May08 0:00
......
终端关键字段解释
USER :进程的用户
PID :进程的ID
%CPU :进程占用的CPU百分比
%MEM :进程占用的内存百分比
VSZ :进程占用的虚拟内尺量(KB)
RSS :进程占用的物理内存量(KB)
TTY :启动进程的终端名,不是从终端启动的进程则显示?
STAT : (进程状态)
- D:不可中断的休眠状态
- R:正在运行的状态
- S:处于休眠状态,可被唤醒
- T:停止状态,可能是在后台暂停或进程处于跟踪调试状态
- Z:僵尸进程,进程已经终止,但是部分程序还在内存当中
- W:内存交互状态(从 2.6 内核开始无效)
- X:死掉的进程(应该不会出现)
- <:高优先级(以下状态在 BSD 格式中出现)。
- N:低优先级。
- L:被锁入内存。
- s:包含子进程。
- l:多线程(小写 L)。
- +:位于后台。
START:进程被触发启动时间
TIME:进程实际使用cpu运行时间
COMMAND:进程的启动命令
2.ps -elf
【示例】
ps -elf
选项说明:
-e:显示系统内的所有进程信息-l:使用长格式显示进程信息-f:使用完整的格式显示进程信息
查看结果如下所示:
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
4 S root 1 0 0 80 0 - 41954 ep_pol May08 ? 04:22:44 /sbin/init
1 S root 2 0 0 80 0 - 0 kthrea May08 ? 00:00:00 [kthreadd]
1 I root 3 2 0 60 -20 - 0 rescue May08 ? 00:00:00 [rcu_gp]
1 I root 4 2 0 60 -20 - 0 rescue May08 ? 00:00:00 [rcu_par_gp]
1 I root 5 2 0 60 -20 - 0 rescue May08 ? 00:00:00 [slub_flushwq]
1 I root 6 2 0 60 -20 - 0 rescue May08 ? 00:00:00 [netns]
1 I root 8 2 0 60 -20 - 0 worker May08 ? 00:00:00 [kworker/0:0H-events_highpri]
1 I root 10 2 0 60 -20 - 0 rescue May08 ? 00:00:00 [mm_percpu_wq]
1 S root 11 2 0 80 0 - 0 rcu_ta May08 ? 00:00:00 [rcu_tasks_rude_]
......
终端关键字段解释
F : 内核分配给进程的系统标记
S : 进程的状态
UID : 启动这些进程的用户
PID: 进程的进程ID
PPID : 父进程的进程号(如果该进程是由另一个进程启动的)
C :进程生命周期中的CPU利用率
PRI: 进程的优先级(越大的数字代表优先级越低)
NI:谦让度值用来参与决定优先级
ADDR: 进程的内存地址/td>
SZ:假如进程被换出,所需交换空间的大致大小
WCHAN:若该进程在睡眠,则显示睡眠中的系统函数名
STIME :进程启动时的系统时间
TTY :进程启动时的终端设备
TIME: 运行进程需要的累计CPU时间
CMD : 进程的启动命令
pidof命令
根据程序名查找对应的进程ID。也就是当你只知道程序名字的时候可以通过该命令查看进程对应的pid。
pidof使用语法:
pidof 选项 进程名
常用选项说明:
-s:只显示一个(单个)PID(通常是第一个)-x:同时显示脚本(例如 /bin/bash script.sh)的PID-o <PID>:忽略指定的PID(例如当前 Shell)
【示例1】查看Nginx进程pid
root@ihavetwocats:~# pidof nginx
2386853 2386852 2386798 876628 876626
【示例2】查看脚本test.sh的进程pid(脚本需要-x选项识别)
root@ihavetwocats:~# pidof -x test.sh
1420
pgrep命令
根据进程名、用户、终端或正则模式查找进程PID,是ps + grep的高效组合命令。
pgrep使用语法:
pgrep 选项 模式
常用选项说明:
-l:显示 PID 和进程名-a:显示 PID 和完整命令行(command line)-u <用户>:仅显示属于指定用户的进程-t <终端>:仅显示来自指定终端的进程-n:显示最近(最新)的一个匹配进程 PID-o:显示最早的一个匹配进程 PID-f:匹配整个命令行(不仅仅是进程名)-v:反向匹配(显示未匹配到的进程)-P <PID>:显示指定进程的子进程
【示例1】根据程序名显示进程pid
root@ihavetwocats:~# pgrep -l nginx
876626 nginx
876628 nginx
2386798 nginx
2386852 nginx
2386853 nginx
【示例2】根据进程pid以完整格式显示子进程和进程名
root@ihavetwocats:~# pgrep -P 876626 -a
876628 nginx: worker process
pstree命令
一个非常直观、实用的进程树查看命令,用于以树状结构展示系统中进程的父子关系。它比ps -ef --forest更简洁,更适合分析进程层级、守护进程及其子进程的关系。
pstree使用语法:
pstree 选项 PID或用户名
常用选项说明:
-p:显示每个进程的 PID(进程号)-u:显示每个进程所属的用户名-a:显示完整的命令行参数-t:显示线程(threads)信息-n:按 PID 数字顺序排序同级进程-h:高亮显示当前终端所属的进程-s:显示指定进程的父进程链-A:使用 ASCII 字符绘制树结构-G:使用 UTF-8 字符绘制树结构-l:不截断长命令行输出-c:不使用缓存,强制重新读取进程信息--show-parents:显示指定进程的所有父进程--highlight-all:高亮显示所有相同名称的进程
【示例1】查看所有进程的进程树
root@ihavetwocats:~# pstree -ap
systemd,1
├─containerd,868
│ ├─{containerd},952
│ ├─{containerd},955
│ ├─{containerd},956
│ ├─{containerd},957
│ ├─{containerd},960
│ ├─{containerd},1132
│ ├─{containerd},1210
│ ├─{containerd},137964
│ └─{containerd},3157496
├─ntpd,3840982 -p /var/run/ntpd.pid -g -u 113:118
│ └─{ntpd},3840983
├─packagekitd,3840968
│ ├─{packagekitd},3840974
│ └─{packagekitd},3840975
├─polkitd,843 --no-debug
│ ├─{polkitd},859
│ └─{polkitd},873
├─rsyslogd,846 -n -iNONE
│ ├─{rsyslogd},874
│ ├─{rsyslogd},875
│ └─{rsyslogd},876
......
【示例2】查看指定进程的进程树
root@ihavetwocats:~# pstree -ap 876626
nginx,876626
└─nginx,876628
查看端口信息
netstat工具
Linux系统中用于显示网络连接、路由表、接口状态等信息的命令,它是网络排查和性能监控中非常常用的工具。
netstat使用语法:
netstat 选项
常用选项说明:
-a:显示所有连接(包括监听和未监听的)-t:显示 TCP 连接-u:显示 UDP 连接-n:以数字形式显示地址和端口(不做域名解析)-l:仅显示监听中的 socket-p:显示使用该端口的进程 PID 与程序名-r:显示路由表-i:显示网络接口信息-s:显示各协议的统计信息-c:持续输出,定时刷新-e:显示扩展信息(包括用户、inode等)-g:显示多播组成员关系
我们常用的选项就是-lnptu,用于查看TCP和UDP协议的进程监听端口。
【示例】
root@ihavetwocats:~# netstat -lnptu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 812/systemd-resolve
tcp 0 0 0.0.0.0:9000 0.0.0.0:* LISTEN 21006/docker-proxy
tcp 0 0 0.0.0.0:9001 0.0.0.0:* LISTEN 20988/docker-proxy
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2388705/docker-prox
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1579/sshd: /usr/sbi
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 2388684/docker-prox
......
终端关键字段解释
Proto:协议类型(tcp、udp等)
Recv-Q:接收队列中未处理的字节数
Send-Q:发送队列中未确认的字节数
Local Address:本地地址(IP:端口)
Foreign Address:远程地址(对端IP:端口)
State:连接状态(LISTEN、ESTABLISHED 等)
- LISTEN:服务器正在监听连接请求
- ESTABLISHED:已建立连接
- TIME_WAIT:等待足够时间以确保对方收到 ACK
- CLOSE_WAIT:等待本地应用关闭连接
- SYN_SENT:已发送连接请求,等待确认
- SYN_RECV:收到连接请求,正在等待确认
- FIN_WAIT1 / FIN_WAIT2:正在关闭连接过程中的状态
- CLOSED:无连接状态
PID/Program name:使用该端口的进程 ID 和程序名
ss工具
ss命令工具是现代Linux系统中替代netstat的网络统计工具,速度更快,功能更强大。
ss工具特点:
- ss(socket statistics)用于查看套接字连接信息。
- 支持 TCP、UDP、UNIX socket 等多种协议。
- 与netstat相比:
- 查询速度快
- 输出字段更丰富
- 支持更多过滤条件
ss使用语法:
ss 选项
常用选项说明:
-t:显示 TCP 连接-u:显示 UDP 连接-l:仅显示监听中的 socket-a:显示所有连接,包括监听和非监听-n:以数字形式显示地址和端口(不做域名解析)-p:显示使用该 socket 的进程信息-r:显示路由表信息-s:显示统计信息(各协议连接数)-o:显示定时器信息(如 TCP 超时)-i:显示接口相关信息-4:仅显示 IPv4 连接-6:仅显示 IPv6 连接
【示例1】查看所有TCP连接
ss -t -a
# 查看监听的 TCP 端口
ss -t -l -n
【示例2】查看所有UDP连接
ss -u -a -n
【示例3】查看每个连接对应的进程
ss -tunlp
【示例4】按端口过滤连接,例如:查看80端口
ss -t -a -n '( sport = :80 or dport = :80 )'
终端关键字段解释
Netid:协议类型(tcp、udp、unix 等)
State:连接状态(LISTEN、ESTAB、TIME-WAIT 等)
- LISTEN:监听状态
- ESTAB:已建立连接
- TIME-WAIT:等待足够时间确认对方收到 ACK
- CLOSE-WAIT:等待本地应用关闭连接
- SYN-SENT:已发送连接请求,等待确认
- SYN-RECV:收到连接请求,等待确认
- FIN-WAIT-1 / FIN-WAIT-2:正在关闭连接过程中的状态
- CLOSED:连接关闭
Recv-Q:接收队列中未处理的字节数
Send-Q:发送队列中未确认的字节数
Local Address:Port:本地 IP 与端口
Peer Address:Port:远程 IP 与端口
Process:使用该 socket 的进程信息
lsof工具
lsof命令工具是Linux系统中用于查看打开文件及占用情况的强大工具,尤其在排查端口被占用或文件锁问题时非常有用。以下内容采用清单列表形式说明。
lsof使用语法:
lsof 选项 选项参数
常用选项说明:
-i:显示网络相关的文件(TCP、UDP、端口)-i :端口号:显示指定端口被哪个进程占用-i TCP/UDP:显示指定协议的网络连接-p PID:显示指定进程打开的文件-u 用户名:显示某个用户打开的文件+D 目录:显示某个目录下打开的文件(递归)-c 命令名:显示指定命令打开的文件-t:只输出PID,适合配合kill使用-n:显示数字形式的地址(不解析主机名)-P:显示端口号而非服务名-r 秒数:定期刷新显示-l:显示锁定文件的信息
【示例1】查看80端口被哪个进程占用
lsof -i:80
【示例2】查看进程1234打开的文件
lsof -p 1234
终端关键字段解释
COMMAND:打开文件的命令名
PID:进程 ID
USER:进程所属用户
FD:文件描述符(如 cwd、txt、mem、0u、1w 等)
TYPE:文件类型(REG、DIR、CHR、FIFO、IPv4、IPv6 等)
DEVICE:设备号
SIZE/OFF:文件大小或偏移量
NODE:节点号
NAME:文件名或网络连接信息(IP:Port)
管理进程操作
进程后台管理
我们通过一个脚本来演示进程后台的管理,test.sh脚本内容如下所示:
#!/bin/bash
status=(start running stop)
while true
do
for i in ${status[@]}; do
sleep 1
done
done
1.进程后台运行符号:&
通常我们使用命令后面加&符号来后台运行进程。
【示例】我们编辑一个脚本来实现死循环保持一直运行状态,然后后台运行
# 后台运行
root@ihavetwocats:~# ./test.sh &
[1] 378625
注意:若关闭终端,进程会被终止(除非使用 nohup、disown 等)。
2.查看后台任务:jobs
我们可以使用jobs命令来查看当前终端后台运行的进程任务。
【示例】查看当前终端的后台任务
root@ihavetwocats:~# jobs
[1]+ Running ./test.sh &
3.调度后台任务:fg
可以通过fg命令将后台任务调回前台。fg后面只需要跟上任务的序号就行,比如:1、2、3等。
【示例】将后台任务调回到前台运行
root@ihavetwocats:~# fg 1
./test.sh
4.重启后台任务:bg
我们可以使用Ctrl + Z快捷键暂停任务,之后我们使用jobs命令能看到任务状态变成Stoped。
【示例1】暂停任务
root@ihavetwocats:~# ./test.sh
^Z
[1]+ Stopped ./test.sh
root@ihavetwocats:~# jobs
[1]+ Stopped ./test.sh
然后使用bg命令重新启动任务,跟fg命令一样后面跟上任务的序号就能重启该任务,重启之后再使用jobs命令查看发现任务重新变成Running状态。
【示例】重启任务
root@ihavetwocats:~# bg 1
[1]+ ./test.sh &
root@ihavetwocats:~# jobs
[1]+ Running ./test.sh &
5.防止挂起:nohup
nohup可以让命令忽略SIGHUP(挂起信号),也就是当终端关闭(或 SSH 断开)时,该进程不会因为收到SIGHUP而被终止。如果只使用&符号可以让进程后台运行,但是一旦终端关闭,任务也会随着被终止。
对于test.sh脚本进行修改添加日志输出的效果,文件如下:
#!/bin/bash
status=(start running stop)
while true
do
for i in ${status[@]}; do
echo "现在状态是 $i ......"
sleep 1
done
done
【示例1】结合nohup + &实现进程后台运行并不受终端关闭所影响
root@ihavetwocats:~# nohup ./test.sh > test.log 2>&1 < /dev/null &
[1] 417397
root@ihavetwocats:~# jobs
[1]+ Running nohup ./test.sh > test.log 2>&1 < /dev/null &
说明:
> test.log:把标准输出写到日志文件(覆盖)。2>&1:把标准错误合并到标准输出里(所以都进同一个文件)。< /dev/null:防止程序试图读 stdin 导致阻塞。
【示例2】如果我们不使用重定向符号>定义输出文件默认会输出到nohup.out文件
root@ihavetwocats:~# nohup ./test.sh 2>&1 < /dev/null &
[1] 416225
root@ihavetwocats:~# nohup: appending output to 'nohup.out'
^C
root@ihavetwocats:~# jobs
[1]+ Running nohup ./test.sh 2>&1 < /dev/null &
root@ihavetwocats:~# ll -h nohup.out
-rw------- 1 root root 13K Oct 13 10:18 nohup.out
补充说明:我们可以结合
$!变量来获取运行进程的PID,将他写入一个pid文件,方便我们查看该进程的PID号,方便管理。还可以结合$?变量来看进程是否运行成功,通常返回0或1,0为成功状态,1则为失败。
我们通过运行一个后台进程,使用$!变量来查看PID,以及使用$?变量来获取运行状态,如下所示:
root@ihavetwocats:~# nohup ./test.sh > test.log 2>&1 < /dev/null &
[1] 420096
root@ihavetwocats:~# echo $!
420096
root@ihavetwocats:~# echo $?
0
终止进程
常用信号速查表
| 信号名 | 编号 | 说明 | |
|---|---|---|---|
| SIGHUP | 1 | 挂起/终端关闭信号,常用来重载配置 | |
| SIGINT | 2 | 中断进程(通常由 Ctrl+C 触发) | |
| SIGQUIT | 3 | 退出进程并生成核心转储core dump | |
| SIGKILL | 9 | 强制终止,无法捕获或忽略 | |
| SIGTERM | 15 | 请求进程优雅退出(可被捕获或忽略),默认 kill 命令发送的信号 | |
| SIGSTOP | 19 | 暂停进程(不可捕获) | |
| SIGCONT | 18 | 继续被暂停的进程 | |
| SIGUSR1 | 10 | 用户自定义信号1 | |
| SIGUSR2 | 12 | 用户自定义信号2 |
1.kill命令
使用kill命令可以终止进程。
kill使用语法:
kill 进程PID
常用选项说明:
-l:列出所有信号名称及对应的编号。-s <信号>:指定要发送的信号,可以用信号名或信号编号。-n <信号编号>:与-s类似,用信号编号指定信号。-L:显示信号名称表(与 -l 功能相同,某些系统有差别)。--signal <信号>:明确指定信号(长格式写法,等价于 -s)。-9:强制杀死进程。
【示例1】杀死单个或多个进程
# 终止指定pid进程
kill 420096
# 终止多个pid进程
kill 417397 420096
【示例2】如果使用kill命令无响应,可以使用-9选项强制终止进程。
# 强制终止进程
kill -9 420096
使用kill杀死后台进程再使用jobs查看后台进程状态,发现状态变成了Terminated,然后一会儿就会消失。如下所示:
root@ihavetwocats:~# kill 426634
root@ihavetwocats:~# jobs
[1]+ Terminated nohup ./test.sh > test.log 2>&1 < /dev/null
2.killall命令
killall用于按进程名称(而不是 PID)杀死进程的命令。
killall使用语法:
killall 选项 进程名
常用选项说明:
-u <用户名>:只杀指定用户的进程。-e:精确匹配进程名(完全一致)。-I:匹配进程名时忽略大小写。-v:显示被杀死的每个进程信息。-q:静默模式,不输出错误信息。-w:等待所有指定进程结束后再返回。-s <信号>:指定发送的信号(默认是 SIGTERM)。-g:杀死指定进程所在的进程组。-r:使用正则表达式匹配进程名(部分发行版支持)。-9:强制杀死进程。-help:显示帮助信息。
【示例1】杀死所有名为python的进程
killall python
【示例2】杀死指定用户为ubuntu并且名为python的进程
killall -u ubuntu python
【示例3】精确匹配进程名(避免部分匹配)
killall -e nginx
3.pkill命令
pkill使用语法:
pkill 选项 进程名
常用选项说明:
-f:匹配完整命令行(包括路径和参数)。-x:精确匹配进程名(完全一致)。-u <用户名>:只匹配指定用户的进程。-P <pid>:只杀死指定父进程的子进程。-n:仅杀死最新启动的匹配进程。-o:仅杀死最早启动的匹配进程。-signal:指定发送的信号,如 -9 表示强制杀死。-l:列出所有信号名称(不执行杀操作)。-t <终端>:匹配在指定终端上运行的进程。-g <pgid>:匹配指定进程组ID的进程。-F <pidfile>:从 PID 文件中读取 PID 并结束对应进程。-e:显示每个匹配进程的退出状态。-9:强制杀死进程。-help:显示帮助信息。
【示例1】杀死所有名为python的进程
pkill python
【示例2】杀死所有命令行中包含 “test.sh” 的进程
pkill -f "test.sh"
【示例3】杀死指定用户为ubuntu并且名为python的进程
pkill -u ubuntu python
【示例4】杀死精确匹配进程名为nginx的(避免部分匹配)
pkill -x nginx
后台任务管理工具:screen
screen是Linux中常用的终端复用工具,它可以让你在一个SSH会话中启动多个虚拟终端,并且即使断开连接,进程也能继续运行。
screen不是严格意义上的Linux内核内置工具,可能需要安装,安装方法如下:
Debian / Ubuntu
apt -y install screen
RedHat / CentOS
yum -y install screen
screen的使用
1.创建一个后台会话取名为test1
screen -S test1
进入screen创建的环境后,执行任务,如下所示:
root@ihavetwocats:~# ./test.sh
现在状态是 start ......
现在状态是 running ......
现在状态是 stop ......
现在状态是 start ......
然后按Ctrl + A + D快捷键退出当前创建的环境,会回到原来的终端界面,如下所示:
root@ihavetwocats:~# screen -S test1
[detached from 445721.test1]
2.查看后台会话
root@ihavetwocats:~# screen -ls
There is a screen on:
445721.test1 (10/13/2025 11:15:13 AM) (Detached)
1 Socket in /run/screen/S-root.
3.重连会话
# 指定重连任务名
screen -r test1
# 或者指定ID
screen -r 445721
结束任务然后输入exit结束会话
root@ihavetwocats:~# screen -r test1
[screen is terminating]
补充说明:也可以在源终端使用
screen -X -S 任务名 quit命令停止启动的后台终端任务。
screen使用快捷键列表
| 快捷键 | 功能 |
|---|---|
| Ctrl + A D | 分离当前会话(后台运行) |
| Ctrl + A C | 创建一个新窗口 |
| Ctrl + A N | 切换到下一个窗口 |
| Ctrl + A P | 切换到上一个窗口 |
| Ctrl + A " | 显示所有窗口列表 |
| Ctrl + A K | 关闭当前窗口 |
| Ctrl + A A | 发送 Ctrl + A 到当前程序 |
| Ctrl + A Esc | 进入滚动模式(可以翻阅历史输出) |
☆常用技巧☆
1.如何排查僵尸进程
查看所有进程状态,筛选僵尸进程。
ps aux | awk '$8=="Z" {print $0}'
可以使用更加简洁的命令来排查。
ps -e -o pid,ppid,state,comm | grep '^.* Z'
使用top工具查看系统当前僵尸进程数量,看zombie计数即可。
top
2.结合进程查看终止进程
可以结合pgrep + kill命令来批量结束所有的进程,如下所示:
kill $(pgrep -f 'test.sh')
3.如何优雅地终止进程
Linux可以通过信号(signal) 来通知进程做某些操作。优雅退出首选SIGTERM,如果进程不响应再用SIGKILL。
1.先发送 SIGTERM(kill/killall/pkill 默认信号)。
kill -s SIGTERM <PID>
2.等待一段时间(比如 5~10 秒),让进程清理资源。
3.检查进程是否还存在。
ps aux | grep <PID>
4.如果仍未退出,使用 SIGKILL 强制终止
kill -s SIGKILL <PID>