前言
[!NOTE] 核心引言 进程是Linux系统资源分配的基本单位,所有系统服务、应用程序和用户操作最终都以进程的形式运行。对于运维人员而言,熟练掌握进程管理是排查系统负载过高、资源泄漏、服务异常等问题的核心技能。本文将系统讲解进程分类、异常进程原理与解决方案、核心查看命令及控制机制,并深入探讨后台进程运行、网络连接查询等高阶主题,适用于所有主流Linux发行版。
一、进程基础与分类
1.1 进程基本概念
进程是程序的一次动态执行过程,拥有独立的内存空间、文件描述符和系统资源。每个进程都有唯一的标识:
- PID (Process ID):进程ID,全局唯一
- PPID (Parent Process ID):父进程ID
- UID/GID:进程所属的用户ID和组ID
Linux系统启动时,第一个运行的进程是 systemd(PID=1),它是所有进程的祖先,负责管理系统服务和回收孤儿进程。
1.2 进程常规分类
| 进程类型 | 特点 | 示例 |
|---|---|---|
| 前台进程 | 运行在终端,占用终端输入输出,用户可直接交互 | 执行 ls、vim 等命令 |
| 后台进程 | 运行在后台,不占用终端,用户无法直接交互 | 命令末尾加 & 执行:sleep 300 & |
| 守护进程 (Daemon) | 特殊的后台进程,随系统启动,持续运行提供服务 | sshd、nginx、crond |
| 内核进程 | 由内核创建,运行在内核态,管理系统资源 | 名称以 [ 开头,如 [kworker]、[kswapd] |
1.3 异常进程详解
[!IMPORTANT] 系统排查关键点 异常进程是导致系统不稳定的常见原因,掌握其特征与处理机制至关重要。
1.3.1 孤儿进程
- 定义:父进程先于子进程退出,子进程失去父进程,成为孤儿进程。
- 处理机制:系统会自动将其收养给
systemd(PID=1),并在子进程退出时自动回收资源。 - 危害:无任何危害,属于正常的系统托管行为,无需人工干预。
1.3.2 僵尸进程
- 定义:子进程先于父进程退出,但父进程没有调用
wait()或waitpid()回收资源,子进程的进程控制块 (PCB) 仍然残留在系统中。 - 核心特点:
- 已经释放了内存、CPU等大部分系统资源,只保留 PCB。
- 持续占用系统 PID 资源池(系统可用 PID 默认约束为 32768)。
- 大量堆积会导致系统无法创建任何新进程。
[!TIP] 僵尸进程终结指南 请按以下优先级顺序尝试解决僵尸进程问题:
# 1. 优雅通知父进程回收子进程kill -17 <父进程PID>
# 2. 如果父进程无响应,则尝试正常终止父进程(终止后僵尸进程转为孤儿,由systemd统一回收)kill -15 <父进程PID>
# 3. 最后通牒:强制干掉父进程!kill -9 <父进程PID>
# 极端情况:如果上述方法全部失效,才考虑重启系统。二、进程查看核心命令
2.1 ps 命令:静态查看进程
[!NOTE] 核心技能
ps用于获取当前时刻的系统进程快照,是日常诊断最基础的利器。
2.1.1 基础语法与参数讲解表
| 参数 | 全称 | 用途说明 | 常见组合 | 示例命令 |
|---|---|---|---|---|
a | all users | 显示所有用户的所有进程 | 必须与 x 组合 | ps aux、ps ax |
u | user format | 采用用户友好的信息输出格式 | 与 ps a 组合 | ps aux |
x | without tty | 显示没有终端的进程(后台进程) | 与 ps a 组合 | ps aux |
-e | every process | 显示系统内的每一个进程 | System V风格 | ps -ef、ps -aux |
-f | full format | 提供完整的进程信息及父子关系 | 与 -e 组合 | ps -ef |
-o | output format | 自定义输出字段(极度灵活) | 精细化查询 | ps -o pid,ppid,cmd |
-C | command | 仅显示指定程序名称的进程 | 快速定位 | ps -C nginx |
-p | pid | 仅显示指定PID的进程信息 | 精准查询 | ps -p 1234,5678 |
-U | user | 仅显示指定用户的所有进程 | 权限审计 | ps -U root |
--forest / --tree | hierarchy | 以树形结构显示进程层级关系 | 依赖分析 | ps --forest -ef |
-H | show process tree | 树形输出父子进程关系 | 父子链追踪 | ps -eH |
L | thread | 显示进程的线程信息 | 多线程诊断 | ps -eLf |
-w | wide output | 禁止输出行宽限制,显示完整命令行 | 长命令查看 | ps auxww |
最常用组合速记:
ps aux # BSD风格,最常用的全能查询命令(务必死记硬背!)ps -ef # System V风格,显示完整进程树及父子关系ps -eH # 树形显示所有进程的调用关系链路ps -C nginx # 快速查询特定程序ps -o pid,ppid,cmd --sort=-%cpu # 自定义格式并按CPU使用率倒序2.1.2 ps aux 输出字段深度解析(模拟输出示例)
实际执行命令 ps aux 的真实输出:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.1 24068 3816 ? Ss Jan08 0:02 /lib/systemd/systemd --system --deserializeroot 45 0.0 0.1 17320 2960 ? Ss Jan08 0:00 /lib/systemd/systemd-journaldroot 123 0.0 0.0 99920 2456 ? Ss Jan08 0:01 /lib/systemd/systemd-udevdmessage+ 234 0.0 0.1 7352 2120 ? Ss Jan08 0:00 /usr/bin/dbus-daemon --system --address=root 456 0.1 0.2 105400 5892 ? Ss Jan08 0:15 /usr/sbin/sshd -Dpostgres 890 0.0 1.2 215640 48920 ? Ss Jan08 0:32 /usr/lib/postgresql/14/bin/postgresxiaoying 1024 0.5 0.8 1542880 32456 ? Sl 10:30 1:23 /usr/bin/python3 /home/xiaoying/app.pyroot 2048 0.0 0.0 21544 1204 pts/0 Ss 10:35 0:00 -bashxiaoying 2234 2.1 3.5 2048000 139876 pts/0 Rl+ 10:36 0:08 java -Xmx512m -jar myapp.jarxiaoying 2345 0.0 0.0 9932 640 pts/0 S+ 10:37 0:00 grep nginxroot 3456 0.0 0.0 0 0 ? S Jan08 0:00 [kworker/0:0-kblockd]root 3789 Z 0.0 0 0 ? Z Jan08 0:00 [defunct]| 字段名 | 示例值 | 含义详解 |
|---|---|---|
USER | root、xiaoying | 进程所属的用户名(哪个账号启动了这个进程) |
PID | 1、2234 | 进程的全局专属唯一标志号 ID(系统内绝不重复) |
%CPU | 0.0、2.1 | 进程正在霸占整个物理 CPU 算力的百分比(多核CPU时为平均占用) |
%MEM | 0.1、3.5 | 进程正在消耗整个物理内存的百分比(与系统总内存相比) |
VSZ | 168684、2048000 | 虚拟内存申请量 (KB):含真实物理内存+交换分区+运行依赖的共享库额度(理论可申请但未必使用) |
RSS | 13284、139876 | 常驻物理内存占用 (KB):实打实扣减的物理内存(不含 Swap 区与共享库,这是真正在用的内存) |
TTY | ?、pts/0 | 进程所绑定的终端器设备,显示 ? 代表为脱离终端控制的后台守护类进程;pts/0 代表伪终端0 |
STAT | Ss、Rl+、Z | 进程当前生存状态特征码(详见下方状态字典表解析) |
START | May10、10:30 | 进程启动时的具体日历时间或时刻 |
TIME | 0:03、1:23 | 进程自出生以来累计占用消耗掉的 CPU 计算时长总和 |
COMMAND | /usr/lib...、/usr/bin/python3 /home/xiaoying/app.py | 调起该进程的完整原生命令行执行路径与携带参数 |
2.1.3 STAT 状态码字典补充
R : (Running) 运行状态,正在 CPU 上执行或处于队列中等待被调度S : (Sleeping) 可中断睡眠,等待特定事件触发,可随时被信号唤醒D : (Disk Sleep) 不可中断睡眠,绝大多数处于深度磁盘 IO 阻塞,无法被常规信号唤醒Z : (Zombie) 僵尸态,程序已实质性终结但骨灰尚未被收容T : (Stopped) 停止态,通常因人为信号暂停或正挂在调试器(GDB)上运行
修饰符号(可跟在主状态后):s : session leader 会话首发进程(控制一个会话的主控权)l : multi-thread 代码处于多线程状态(含多个执行线程)+ : foreground 隶属于前台进程组(当前在终端上活跃交互)- : background 后台进程,不在前台进程组中< : high priority 高优先级进程(通过 nice 值提权)N : low priority 低优先级进程(通过 nice 值降权)2.1.4 pstree 命令:进程树形结构展示
pstree 以树形结构清晰展示进程的父子关系,比 ps --forest 更加直观美观。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例命令 |
|---|---|---|---|
-p | show pids | 同时显示每个进程的PID号 | pstree -p |
-u | show uid | 显示进程所属的用户名变化 | pstree -u |
-a | show args | 显示每个进程的完整命令行参数 | pstree -a |
-l | long lines | 不限制输出行宽,完整显示长命令 | pstree -l |
-h | highlight | 高亮显示当前进程及其祖先 | pstree -h |
-s <pid> | show subtree | 只显示指定进程的子树 | pstree -s 1234 |
-A | ASCII | 使用ASCII字符绘制树形结构 | pstree -A |
模拟输出示例:
# 执行: pstree -psystemd(1)─┬─systemd-journald(45) ├─systemd-udevd(123) ├─sshd(456)─┬─sshd(2048)───bash(2050)───vim(2051) │ └─sshd(3000)───bash(3002) ├─postgres(890)─┬─postgres(891) │ ├─postgres(892) │ └─postgres(893) ├─nginx(1200)─┬─nginx(1201) │ └─nginx(1202) └─...
# 执行: pstree -pu xiaoyingsystemd(1)─┬─... ├─gnome-shell(2100,xiaoying)─┬─evolution(2101,xiaoying) │ └─nautilus(2102,xiaoying) ├─java(2234,xiaoying)─┬─{java}(2235,xiaoying) │ ├─{java}(2236,xiaoying) │ └─... └─...实战应用:
pstree -p -u # 显示PID和用户信息的进程树pstree -p bash # 仅显示bash进程及其子树pstree -s 2234 # 显示PID 2234这个进程的完整祖先链路pstree -a -p java # 显示java进程树并附带完整命令行参数2.2 top 命令:实时监视系统脉搏
[!NOTE] 核心技能
top是 Linux 性能瓶颈分析的万金油工具。命令行输入top并回车后,系统整体运行大盘面板将实时动态展现。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例命令 |
|---|---|---|---|
-b | batch mode | 非交互式模式,直接输出然后退出(适合脚本调用) | top -b -n 1 |
-n <num> | number of iterations | 执行指定次数的刷新后自动退出 | top -b -n 3 |
-d <sec> | delay | 设置刷新周期(默认3秒) | top -d 1 |
-p <pid> | monitor pids | 仅监视指定PID的进程 | top -p 1234,5678 |
-u <user> | user filter | 仅显示指定用户的进程 | top -u xiaoying |
-i | idle processes | 不显示闲置进程 | top -i |
-1 | single cpu | 分别显示每个CPU核心的负载(不汇总) | top -1 |
-s <col> | sort by column | 按指定列排序(需指定列号) | top -s %CPU |
-H | threads | 显示线程级别的信息而非进程级别 | top -H |
2.2.1 top 交互模式详解
执行 top 命令后的实时输出示例:
top - 10:30:45 up 2 days, 4:50, 2 users, load average: 0.15, 0.08, 0.05Tasks: 120 total, 1 running, 119 sleeping, 0 stopped, 0 zombie%Cpu(s): 0.3 us, 0.2 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stMiB Mem : 7859.2 total, 4521.3 free, 1234.5 used, 2103.4 buff/cacheMiB Swap: 8192.0 total, 8192.0 free, 0.0 used. 6234.1 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2234 xiaoying 20 0 2048000 139876 45678 R 2.1 3.5 1:23.45 java -Xmx512m 1024 xiaoying 20 0 1542880 32456 12345 S 0.5 0.8 1:23.12 python3 /home/xiaoying/app.py 890 postgres 20 0 215640 48920 32100 S 0.0 1.2 0:32.56 /usr/lib/postgresql/14/bin/postgres 456 root 20 0 105400 5892 3456 S 0.1 0.2 0:15.23 /usr/sbin/sshd -D 123 root 20 0 99920 2456 1234 S 0.0 0.0 0:01.45 /lib/systemd/systemd-udevd 1 root 20 0 24068 3816 2345 S 0.0 0.1 0:02.34 /lib/systemd/systemd --system 234 message+ 20 0 7352 2120 1234 S 0.0 0.1 0:00.56 /usr/bin/dbus-daemon --system 3456 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 [kworker/0:0-kblockd]2.2.2 第 1 行:系统运转概况与生存压力指标
| 指标字段 | 样例输出 | 极限值与运维含义剖析 |
|---|---|---|
| Top Status | top - 10:30:45 | 主机操作系统现在的标准时间戳。 |
| Up Time | up 2 days, 4:50 | 系统自从上次开机后已连续安全运行的具体时长。 |
| Users | 2 users | 当前正在有几个终端用户挂接到这台服务器。 |
| Load average | 0.15, 0.08, 0.05 | 最核心的排队负载数字!分别代表系统过去 1分钟、5分钟、15分钟 内的平均负载队列。警戒法则:一旦此数值长期超过系统物理 CPU 核心总数,意味着系统陷入严重拥堵卡顿!单核CPU警戒线为1.0,8核CPU警戒线为8.0。 |
2.2.3 第 2 行:全量进程生死账本统计
| 状态类别 | 样例数字 | 运维含义剖析 |
|---|---|---|
| Tasks | 120 total | 系统目前注册在案的所有进程总计数量。 |
| running | 1 | 正在使用物理 CPU 处理业务或者排在执行栈首位随时发动的进程数。 |
| sleeping | 119 | 陷入沉睡状态等待各种网络数据返回或定时器唤醒的进程数。 |
| stopped | 0 | 被断点调试卡住或被暂停信号定身的挂起级进程数。 |
| zombie | 0 | 高危重点观测区!已经死亡但未经父进程回收的僵尸进程堆积量,如该数值长期不为 0 则必须干预。 |
2.2.4 第 3 行:CPU 核心算力压榨拆解 (%Cpu)
| 参数 | 样例 | 缩写全称 | 性能瓶颈判断依据 |
|---|---|---|---|
us | 0.3 | User Space | 用户态占用:普通应用程序(如 Tomcat / Nginx 等)吃掉的算力百分比。正常应在10%-70%之间。 |
sy | 0.2 | System Space | 系统态占用:内核底层的调度算法及驱动层消耗掉的算力。若持续超过20%需排查内核 BUG 或驱动问题。 |
ni | 0.0 | Nice | 提权损耗:被通过 renice 修改过调度优先权的人工调整型进程消耗占比。 |
id | 99.5 | Idle Space | 大盘闲置率:CPU 剩余尚未分配出去的空暇能力。越高代表系统越宽松。若id<30%代表CPU处于高负载。 |
wa | 0.0 | Wait I/O | 磁盘阻塞灾难预警:等待底层硬盘存储设备读写反馈的干耗时间。致命红线:若长时间处于并超过 15%~20%,代表你的磁盘 IO 性能已经被彻底打穿!此时应立即排查磁盘读写瓶颈。 |
hi | 0.0 | Hard IRQ | 硬件中断占用:外部硬件设备(如网卡、磁盘)发起的中断抢占占比。若超过5%代表有频繁的硬件中断。 |
si | 0.0 | Soft IRQ | 软中断占用:系统内生软级别中断(如网络数据包处理)的占比。若持续超过10%代表网络处理繁重。 |
st | 0.0 | Steal Time | 虚拟机被宿主掠夺率:在虚拟机环境中,被宿主CPU强制抢占的时间占比。物理机此值为0。 |
2.2.5 第 4 & 5 行:内存水池与交换分区 (Mem & Swap)
| 存储类型 | Total 总池 | Free 净空 | Used 实耗 | 动态缓冲域 / 预估备转资金池 |
|---|---|---|---|---|
| MiB Mem (内存条物理总量) | 7859.2 | 4521.3 | 1234.5 | 2103.4 (buff/cache)用于加速文件读写的缓冲内存,这部分是活钱,当系统告急时内核会自动吐出来救火。实际可用内存 = Free + buff/cache。 |
| MiB Swap (硬盘低速顶替量) | 8192.0 | 8192.0 | 0.0 | 6234.1 (avail Mem)这是真正评估系统”还能容纳启动多少新进程”的可动用活水总容量指标。若avail Mem 接近0则系统面临内存枯竭风险。 |
2.2.6 top 高效交互快捷键与参数
| 按键 | 功能执行逻辑 |
|---|---|
P / M / T | 快捷将进程列表分别强制按照 CPU降序 / 内存降序 / 运行时长降序 重新排列整理。 |
1 | 当面对 8 核 16 核等多 CPU 阵列时,打散汇总数据,独立展开每一个核心的实时负载柱状图。 |
c | 将默认被截断的进程短名,全景展开显示出具体的完整带参命令行启动路径。 |
k | 眼见为实:不退出观测界面的情况下,直接输入目标进程 PID 执行就地格杀指令。 |
f | 进入字段选择模式,可自定义选择要显示哪些列信息。 |
i | 切换是否显示闲置进程,可让输出更加洁净。 |
u | 按用户名过滤显示进程(输入用户名后按Enter)。 |
o | 自定义排序字段,非常灵活的排序选项。 |
W | 将当前的配置保存到 ~/.toprc 文件,下次启动时保持配置。 |
q | 退出 top 程序。 |
h | 显示帮助信息。 |
2.3 htop 命令:比 top 更强大的实时监控工具
htop 是 top 的现代化增强版本,提供了更好的用户界面、更丰富的颜色高亮和更灵活的交互体验。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例命令 |
|---|---|---|---|
-C | no-color | 禁用彩色输出 | htop -C |
-d <delay> | delay | 设置刷新间隔(以1/10秒为单位) | htop -d 30 |
-u <user> | user | 仅显示指定用户的进程 | htop -u xiaoying |
-p <pid> | pid | 仅监视指定PID | htop -p 1234 |
-t | tree | 以树形结构显示进程关系 | htop -t |
-s <col> | sort-key | 按指定列排序 | htop -s PERCENT_CPU |
-H | hide-threads | 隐藏线程信息,仅显示进程 | htop -H |
--pid=<pid> | monitor-pid | 监控指定进程及其子进程 | htop --pid=1234 |
--filter=<str> | filter | 按命令名过滤进程 | htop --filter=nginx |
模拟输出示例:
[红色CPU柱状图] ████████░░░ 58.2% CPU[黄色内存柱状图] ██████░░░░░░ 45.3% Mem[绿色交换柱状图] ██░░░░░░░░░░░░░░░░░░ 2.1% Swp
PID USER PR NI VIRT RES SHR S CPU% MEM% TIME+ Command 2234 xiaoy 20 0 2048M 140M 45M R 45.8 3.5 1:23:45 java -Xmx512m 1024 xiaoy 20 0 1542M 32M 12M S 5.2 0.8 1:23:12 python3 app.py 890 post 20 0 210M 47M 31M S 0.0 1.2 0:32:56 postgres 456 root 20 0 103M 5M 3M S 0.1 0.2 0:15:23 sshd -D 123 root 20 0 97M 2M 1M S 0.0 0.0 0:01:45 systemd-udevd 1 root 20 0 23M 3M 2M S 0.0 0.1 0:02:34 systemd 234 messa 20 0 7M 2M 1M S 0.0 0.1 0:00:56 dbus-daemon 3456 root 0 -20 0B 0B 0B S 0.0 0.0 0:00:00 [kworker/0:0]快捷键对比:
| 按键 | 说明 |
|---|---|
F1 或 h | 打开帮助信息 |
F2 或 S | 打开设置菜单 |
F3 或 / | 搜索进程 |
F4 或 \ | 按名称过滤进程 |
F5 或 t | 切换树形/列表视图 |
F6 或 < > | 改变排序列 |
F7 F8 | 调整进程优先级 (nice值) |
F9 或 k | 发送信号到进程 |
F10 或 q | 退出htop |
L | 显示进程打开的文件和网络连接 |
I | 反转排序顺序 |
+ / - | 展开/折叠进程树 |
实战应用:
htop -u xiaoying # 只看xiaoying用户的进程htop -t # 以树形显示进程关系htop -p 2234 # 单独监视PID 2234这个进程htop -s PERCENT_CPU # 按CPU使用率排序(降序)三、进程控制核心命令
3.1 信号系统详解
Linux 操作系统的核心调度法则依赖于传递不同等级的控制信号量。
| 信号ID | 定义名 | 场景特征 | 是否可被捕捉 |
|---|---|---|---|
1 | SIGHUP | 挂起挂断:让服务无感平滑重载最新修改的配置文件(不彻底断开用户连接) | ✓ 可捕捉 |
2 | SIGINT | 中断信号:用户按 Ctrl+C 时发送,通知进程立即中断 | ✓ 可捕捉 |
3 | SIGQUIT | 退出信号:用户按 Ctrl+\ 时发送,类似SIGINT但会生成核心转储文件 | ✓ 可捕捉 |
9 | SIGKILL | 致命处决:绝对不可屏蔽捕捉的信号,在系统底层被强制剥夺生命周期 | ✗ 不可捕捉 |
15 | SIGTERM | 温柔遣散:系统默认发送指令,允许进程在死前做完诸如持久化数据、清理缓存等收尾行为 | ✓ 可捕捉 |
17/20 | SIGCHLD | 子进程状态变化:告知父进程子进程已退出或被暂停,用于僵尸进程回收 | ✓ 可捕捉 |
19 | SIGSTOP | 暂停进程:暂停进程执行,不能被捕捉或忽略 | ✗ 不可捕捉 |
18 | SIGCONT | 恢复进程:恢复被暂停的进程继续执行 | ✓ 可捕捉 |
信号优先级使用策略:
- 优先使用 SIGTERM (15):给进程优雅退出的机会,释放资源
- 其次尝试 SIGINT (2):模拟 Ctrl+C,通常也能温和停止
- 最后才用 SIGKILL (9):强制杀死,但可能导致资源泄漏
[!CAUTION] 慎用极限击杀指令 在对业务核心数据库(如 MySQL/Redis/PostgreSQL)执行裁决操作时,必须避免直接投喂
kill -9!这种物理切断极易诱发致命的事务中断报错及持久化文件数据产生不可逆转甚至根本无法修复的物理级损坏现象。应先尝试kill -15或通过数据库客户端关闭。
3.2 进程控制指令群组运用
3.2.1 kill 命令:基于PID精准击杀
参数讲解表:
| 参数 | 用途说明 | 示例 |
|---|---|---|
-l | 列出所有可用的信号列表 | kill -l |
-1 <PID> | 发送 SIGHUP 信号,让进程重新读取配置(平滑重启) | kill -1 1234 |
-2 <PID> | 发送 SIGINT 信号,相当于 Ctrl+C | kill -2 1234 |
-9 <PID> | 发送 SIGKILL 信号,强制杀死进程(不可捕捉) | kill -9 1234 |
-15 <PID> | 发送 SIGTERM 信号,温和请求进程退出(kill 默认值) | kill -15 1234 或 kill 1234 |
-TERM <PID> | 同 -15,按信号名而非ID发送 | kill -TERM 1234 |
-STOP <PID> | 发送 SIGSTOP 信号,暂停进程执行 | kill -STOP 1234 |
-CONT <PID> | 发送 SIGCONT 信号,继续已暂停的进程 | kill -CONT 1234 |
模拟场景与命令:
# 场景1:优雅停止Nginx服务(给它保存配置的机会)kill -15 $(pgrep -f "nginx: master")
# 场景2:强制杀死多个java进程kill -9 1234 5678 9012
# 场景3:平滑重载Nginx配置(不中断现有连接)kill -1 $(pgrep -f "nginx: master")
# 场景4:暂停一个长时间运行的脚本kill -STOP 2345
# 场景5:恢复暂停的脚本kill -CONT 2345
# 场景6:列出所有可用信号kill -l3.2.2 pkill 命令:按名称或权限范围轰炸
pkill 支持按照进程名称、用户、终端等属性批量操作进程,相比 kill 更加灵活。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-u <user> | user | 仅终止指定用户的进程 | pkill -u xiaoying |
-U <user> | real user | 按真实用户ID过滤(区分setuid程序) | pkill -U root |
-t <tty> | terminal | 仅终止指定终端上的进程 | pkill -t pts/0 |
-x | exact match | 启动严苛的字面精确匹配,避免误伤 | pkill -x java |
-f | full | 匹配完整的命令行参数,不仅仅是程序名 | pkill -f "python app.py" |
-g <pgrp> | pgroup | 按进程组ID终止 | pkill -g 2048 |
-s <sid> | session | 按会话ID终止(如终止整个SSH会话) | pkill -s 1000 |
-P <ppid> | parent pid | 按父进程ID终止该进程的所有子进程 | pkill -P 1234 |
-n | newest | 仅终止最新匹配的进程 | pkill -n nginx |
-o | oldest | 仅终止最旧的匹配进程 | pkill -o nginx |
-l | list | 列出匹配的进程但不终止(仅列表,不执行) | pkill -l nginx |
--signal <sig> | signal | 指定发送的信号类型 | pkill --signal=TERM nginx |
模拟场景与命令:
# 场景1:温和停止所有nginx进程(允许优雅退出)pkill -15 nginx
# 场景2:强制杀死用户xiaoying的所有进程(紧急情况下隔离用户)pkill -9 -u xiaoying
# 场景3:精确匹配java进程名,避免误杀包含java名的其他程序pkill -x java
# 场景4:终止指定Python脚本(按完整命令行匹配)pkill -f "python /home/xiaoying/app.py"
# 场景5:列出(不终止)所有匹配postgres的进程pkill -l postgres
# 场景6:强制杀死某个SSH终端上的所有进程pkill -9 -t pts/1
# 场景7:仅终止最新启动的nginx进程pkill -n -15 nginx
# 场景8:按父进程ID终止其子进程(孤立某个服务)pkill -P 456
# 场景9:使用正则表达式匹配(需要加上-f参数)pkill -f "python.*app"3.2.3 killall 命令:通过完整名称同名进程扫荡
killall 与 pkill 类似,但仅支持按进程名称匹配,不支持更复杂的过滤条件。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-u <user> | user | 仅终止指定用户运行的进程 | killall -u xiaoying httpd |
-g | process group | 按进程组终止 | killall -g processname |
-i | interactive | 交互模式,每个进程都要求确认 | killall -i nginx |
-l | list | 列出所有可用信号 | killall -l |
-q | quiet | 不输出详细信息 | killall -q nginx |
-r <regex> | regex | 使用正则表达式匹配进程名 | killall -r "java.*" |
-s <signal> | signal | 指定发送的信号 | killall -s TERM nginx |
-v | verbose | 显示详细的操作信息 | killall -v nginx |
-9 / -KILL | kill signal | 强制杀死(直接附加) | killall -9 apache2 |
模拟场景与命令:
# 场景1:温和停止所有apache2进程killall -15 apache2# 或简写为:killall apache2
# 场景2:强制杀死所有httpd进程killall -9 httpd
# 场景3:交互式终止(每个进程都要确认)killall -i nginx
# 场景4:仅终止指定用户xiaoying的python进程killall -u xiaoying python
# 场景5:使用正则表达式杀死所有java进程变种killall -r "java.*"
# 场景6:安静模式,不输出操作信息killall -q httpd
# 场景7:显示详细操作日志killall -v nginx三种进程杀取指令对比:
| 特性 | kill | pkill | killall |
|---|---|---|---|
| 按PID精准杀取 | ✓ | ✗(需结合其他命令获取PID) | ✗ |
| 按进程名批量杀取 | ✗ | ✓ | ✓ |
| 支持正则表达式 | ✗ | ✓ | ✓ (部分支持) |
| 按用户过滤 | ✗ | ✓ | ✓ |
| 按TTY终端过滤 | ✗ | ✓ | ✗ |
| 按父进程ID过滤 | ✗ | ✓ | ✗ |
| 交互式确认 | ✗ | ✗ | ✓ |
| 常见程度 | ★★★★★ | ★★★★☆ | ★★★☆☆ |
3.3 pgrep / pidof 命令:快速查找进程ID
当需要获取进程ID用于后续操作时,这两个命令极其高效。
3.3.1 pgrep 命令详解
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-u <user> | user | 仅查找指定用户的进程 | pgrep -u root nginx |
-U <user> | real user | 按真实用户ID过滤 | pgrep -U xiaoying |
-g <pgrp> | pgroup | 按进程组过滤 | pgrep -g 2048 |
-s <sid> | session | 按会话ID过滤 | pgrep -s 1000 |
-P <ppid> | parent pid | 找出指定父进程的所有子进程 | pgrep -P 1234 |
-l | list | 同时显示进程名和PID | pgrep -l nginx |
-a | full | 显示完整的命令行 | pgrep -a java |
-f | full | 在完整命令行中搜索,不仅仅是进程名 | pgrep -f "python app.py" |
-x | exact | 精确匹配进程名(完全相等) | pgrep -x java |
-n | newest | 返回最新匹配的进程的PID | pgrep -n nginx |
-o | oldest | 返回最旧匹配的进程的PID | pgrep -o nginx |
-c | count | 统计匹配进程的数量 | pgrep -c nginx |
模拟输出示例:
# 执行: pgrep nginx120012011202
# 执行: pgrep -l nginx1200 nginx1201 nginx1202 nginx
# 执行: pgrep -a java2234 /usr/bin/java -Xmx512m -jar myapp.jar
# 执行: pgrep -c nginx3
# 执行: pgrep -u xiaoying102422342345
# 执行: pgrep -P 4567898901000实战应用:
# 快速获取nginx主进程PID并发送信号kill -HUP $(pgrep -o nginx)
# 统计某个用户有多少个进程pgrep -u xiaoying -c
# 列出所有python脚本进程pgrep -l -f "python"
# 找出所有子进程pgrep -P $(pgrep -o nginx)
# 获取最新的java进程并强制杀死kill -9 $(pgrep -n java)3.3.2 pidof 命令详解
pidof 与 pgrep 功能相似但更简洁,主要用于快速查找进程ID。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-s | single | 仅返回一个PID(通常是最新的) | pidof -s nginx |
-x | scripts | 也查找shell脚本(不仅仅是二进制程序) | pidof -x bash |
-o <pid> | omit | 排除指定PID的结果 | pidof -o 1234 nginx |
模拟输出示例:
# 执行: pidof nginx1200 1201 1202
# 执行: pidof -s nginx1202
# 执行: pidof java2234
# 执行: pidof -x bash2048 3002 4521pgrep vs pidof 对比:
| 特性 | pgrep | pidof |
|---|---|---|
| 过滤功能丰富程度 | ★★★★★ (支持用户、TTY、进程组等) | ★★☆☆☆ (基础功能) |
| 正则表达式支持 | ✓ | ✗ |
| 显示进程名 | ✓ (加-l参数) | ✗ |
| 返回多个PID | ✓ | ✓ |
| 仅返回单个PID | ✓ (加-n/-o参数) | ✓ (加-s参数) |
| 常见程度 | ★★★★☆ | ★★★☆☆ |
四、后台进程运行与管理
4.1 后台进程基础概念
后台进程是指脱离终端控制、在系统后台运行的进程。掌握后台进程的运行方法对于服务器管理至关重要。
4.1.1 前台进程与后台进程的切换
# 方式1:在命令末尾加 & 使其运行在后台sleep 300 &
# 方式2:在已运行的前台进程中按 Ctrl+Z 暂停,再使用 bg 命令转为后台运行# 用户正在运行: sleep 300# 按 Ctrl+Z[1]+ Stopped sleep 300bg 1 # 将暂停的作业转为后台运行
# 方式3:使用 fg 命令将后台进程调回前台fg %1
# 方式4:查看当前终端的所有后台作业jobs # 显示所有后台作业jobs -l # 显示后台作业及其PIDjobs -r # 仅显示运行中的后台作业jobs -s # 仅显示已停止的后台作业模拟场景演示:
$ sleep 100 &[1] 2345$ sleep 200 &[2] 2346$ jobs[1]- Running sleep 100 &[2]+ Running sleep 200 &$ fg %1sleep 100# 用户按 Ctrl+Z^Z[1]+ Stopped sleep 100$ bg %1[1]+ sleep 100 &$ jobs -l 2345 Running sleep 100 & 2346 Running sleep 200 &$ kill %2[2]+ Terminated sleep 200$ jobs[1]- Running sleep 100 &4.2 nohup 命令:免疫终端关闭的后台运行
nohup (no hangup) 用于运行那些需要长期后台执行、且要免疫终端关闭信号的进程。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
| (无参数) | command | 需要运行的命令 | nohup python app.py |
--help | help | 显示帮助信息 | nohup --help |
--version | version | 显示版本信息 | nohup --version |
核心特性:
- 自动忽略 SIGHUP 信号(当终端关闭时不会被杀死)
- 自动将标准输出重定向到
nohup.out文件 - 自动将标准错误也重定向到
nohup.out文件
模拟场景与命令:
# 场景1:基础使用,让Python脚本在后台持续运行nohup python /home/xiaoying/app.py &
# 场景2:自定义输出文件,而非默认的nohup.outnohup python /home/xiaoying/app.py > /var/log/app.log 2>&1 &
# 场景3:在脚本中使用nohup运行多个后台任务nohup bash -c ' python app1.py & python app2.py & wait' > /var/log/tasks.log 2>&1 &
# 场景4:使用nohup运行一个需要长时间编译的任务nohup ./configure --prefix=/usr/local && make && make install > build.log 2>&1 &
# 场景5:运行一个带参数的复杂命令nohup java -Xmx512m -Xms512m -jar myapp.jar --config=/etc/myapp.cfg > /var/log/java.log 2>&1 &
# 检查进程是否仍在运行ps aux | grep "python app.py"
# 查看输出日志tail -f nohup.out # 实时查看cat nohup.out # 查看全文nohup 输出重定向详解:
# 标准用法:既捕捉标准输出,也捕捉错误输出nohup command > output.log 2>&1 &
# 拆解说明:# > output.log : 将标准输出(STDOUT, fd=1)重定向到output.log# 2>&1 : 将标准错误(STDERR, fd=2)重定向到标准输出(&1),即也重定向到output.log# & : 整个命令在后台执行
# 如果不想保留输出(仅在后台安静运行):nohup command > /dev/null 2>&1 &
# 分别保存标准输出和错误输出到不同文件:nohup command > stdout.log 2> stderr.log &4.3 & 操作符:简单的后台运行
& 是shell的内置操作符,用于将进程放入后台执行,但不能免疫SIGHUP信号(关闭终端时进程会被杀死)。
参数讲解表:
| 操作 | 说明 | 示例 |
|---|---|---|
command & | 将命令放入后台执行,立即返回提示符 | sleep 300 & |
command1 & command2 & | 同时启动多个后台进程 | task1 & task2 & task3 & |
(command1 & command2) & | 创建子shell并让其内的所有命令后台运行 | (python app1.py & python app2.py) & |
command > /dev/null 2>&1 & | 后台运行并丢弃所有输出 | yes > /dev/null 2>&1 & |
模拟场景与命令:
# 场景1:简单的后台运行sleep 300 &
# 模拟输出# [1] 2345# 返回提示符
# 场景2:同时启动多个后台任务python task1.py & python task2.py & python task3.py &
# 场景3:让后台进程不占用终端输出./long_running_task > /dev/null 2>&1 &
# 场景4:使用子shell管理多个相关任务(while true; do echo "task 1"; sleep 10; done) & \(while true; do echo "task 2"; sleep 10; done) &
# 场景5:后台运行编译任务(带进度输出)make all > build.log 2>&1 &
# 查看后台作业jobs
# 在前台等待后台作业完成wait
# 等待特定的后台作业wait %1wait 2345
# 向后台作业发送信号fg %1 # 将后台作业调回前台kill %1 # 杀死第1个后台作业kill %2 %3 # 同时杀死多个后台作业关键警告:使用 & 运行的进程在终端关闭时会被SIGHUP信号杀死,因此在实际生产环境中应该使用 nohup 或其他工具。
4.4 screen 命令:虚拟终端管理
screen 是一个功能强大的终端复用工具,可以创建多个虚拟终端会话,即使SSH连接断开,会话中的进程也能继续运行。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-S <name> | session-name | 创建命名会话 | screen -S myapp |
-d | detach | 后台创建会话(不立即进入) | screen -d -S worker |
-r <session> | reattach | 重新连接到已存在的会话 | screen -r myapp |
-R <session> | reattach-or-create | 连接或创建会话 | screen -R myapp |
-ls | list | 列出所有会话 | screen -ls |
-x <session> | multiplex | 多个用户共享同一个会话 | screen -x myapp |
-D <session> | force-detach | 强制断开其他连接,然后连接该会话 | screen -D -r myapp |
-m <command> | run-command | 直接运行命令不进入shell | screen -S test -m java -jar app.jar |
-c <file> | config | 使用指定的配置文件 | screen -c ~/.screenrc |
-d -m <cmd> | daemon mode | 后台运行命令 | screen -d -m python app.py |
-wipe | cleanup | 清理已死亡的会话 | screen -wipe |
模拟场景与命令:
# 场景1:创建一个名为myapp的新会话并进入screen -S myapp
# 场景2:在会话内运行一个长期任务# (在screen会话内执行)$ python /home/xiaoying/app.py
# 场景3:从会话内分离出来(回到原终端),会话继续运行# 按 Ctrl+A,然后按 d# 提示: [detached from myapp]
# 场景4:列出所有screen会话screen -ls# 输出示例:# There are screens on:# 3456.myapp (2025-01-09 10:30) (Detached)# 3789.test (2025-01-09 10:25) (Attached)# 2 Sockets in /run/screen/S-xiaoying.
# 场景5:重新连接到分离的会话screen -r myapp
# 场景6:后台创建并运行任务(不进入会话)screen -d -m -S worker python /home/xiaoying/worker.py
# 场景7:列出会话后,强制连接(如果有其他连接则断开它)screen -D -r myapp
# 场景8:多个用户共享一个会话(协作调试)# 用户1:screen -d -m -S shared python app.pyscreen -r shared
# 用户2:screen -x shared
# 场景9:后台批量运行多个任务screen -d -m -S task1 python task1.pyscreen -d -m -S task2 python task2.pyscreen -d -m -S task3 python task3.py
# 场景10:定期检查会话状态for session in $(screen -ls | grep -oP '\d+\.\w+' | cut -d. -f2); do echo "Session: $session" screen -S $session -X hardcopy /tmp/screen_$session.logdone
# 场景11:清理所有已死亡的会话screen -wipescreen 内部快捷键:
| 快捷键 | 功能说明 |
|---|---|
Ctrl+A, d | 分离当前会话(会话在后台继续运行) |
Ctrl+A, c | 创建新的窗口(在同一会话内) |
Ctrl+A, n | 切换到下一个窗口 |
Ctrl+A, p | 切换到上一个窗口 |
Ctrl+A, 0-9 | 直接切换到指定窗口编号 |
Ctrl+A, " | 列出所有窗口,选择后跳转 |
Ctrl+A, A | 重命名当前窗口 |
Ctrl+A, k | 关闭当前窗口 |
Ctrl+A, S | 水平分割窗口 |
Ctrl+A, | | 竖直分割窗口 |
Ctrl+A, X | 关闭当前分割区域 |
Ctrl+A, Tab | 在分割区域间切换 |
Ctrl+A, ? | 显示帮助信息 |
Ctrl+A, : | 进入命令模式(输入screen命令) |
4.5 tmux 命令:现代的终端复用工具
tmux 是 screen 的现代替代品,提供了更灵活的布局、更好的配置和更直观的快捷键。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
new-session -s <name> | new | 创建新会话 | tmux new-session -s myapp |
new-window -n <name> | new window | 在会话内创建新窗口 | tmux new-window -n editor |
split-window -h | horizontal | 水平分割窗格 | tmux split-window -h |
split-window -v | vertical | 竖直分割窗格 | tmux split-window -v |
attach-session -t <name> | attach | 连接到指定会话 | tmux attach-session -t myapp |
list-sessions / ls | list | 列出所有会话 | tmux ls |
list-windows | windows | 列出当前会话的所有窗口 | tmux list-windows |
kill-session -t <name> | kill | 关闭指定会话 | tmux kill-session -t myapp |
kill-window -t <name> | kill window | 关闭指定窗口 | tmux kill-window -t myapp:0 |
send-keys -t <target> <keys> | send | 向指定窗口/窗格发送按键或命令 | tmux send-keys -t myapp "python app.py" Enter |
new-session -d -s <name> <cmd> | daemon | 后台创建会话并运行命令 | tmux new-session -d -s worker python app.py |
tmux 会话/窗口/窗格的层级关系:
tmux Session (会话,一个独立的工作空间) ├── Window 1 (窗口1,可在会话内切换) │ ├── Pane 1.1 (窗格,一个shell会话) │ ├── Pane 1.2 │ └── Pane 1.3 ├── Window 2 │ ├── Pane 2.1 │ └── Pane 2.2 └── Window 3 └── Pane 3.1模拟场景与命令:
# 场景1:创建一个新的tmux会话tmux new-session -s myapp
# 场景2:在后台创建会话并运行Python脚本tmux new-session -d -s worker python /home/xiaoying/worker.py
# 场景3:列出所有tmux会话tmux ls# 输出示例:# myapp: 3 windows (created Wed Jan 8 10:30:45 2025) [120x40]# worker: 1 windows (created Wed Jan 8 10:32:15 2025) (detached) [120x40]
# 场景4:连接到指定会话tmux attach-session -t myapp
# 场景5:在会话内创建新窗口并命名tmux new-window -t myapp -n editor
# 场景6:在指定窗口内分割窗格(水平和竖直)tmux split-window -t myapp:0 -h # 水平分割tmux split-window -t myapp:0 -v # 竖直分割
# 场景7:在指定窗格运行命令(不进入交互式)tmux send-keys -t myapp:0.0 "python app.py" Entertmux send-keys -t myapp:0.1 "tail -f /var/log/app.log" Enter
# 场景8:后台启动多个相关任务tmux new-session -d -s devtmux send-keys -t dev "cd /home/xiaoying/project && npm install" Entertmux new-window -t dev -n servertmux send-keys -t dev:server "npm run dev" Entertmux new-window -t dev -n logstmux send-keys -t dev:logs "tail -f logs/*" Enter
# 场景9:在特定窗格内执行多行命令tmux send-keys -t myapp:0.0 " cd /home/xiaoying/project source venv/bin/activate python app.py" Enter
# 场景10:列出指定会话的所有窗口tmux list-windows -t myapp
# 场景11:关闭指定会话tmux kill-session -t myapp
# 场景12:关闭特定窗口tmux kill-window -t myapp:1
# 场景13:批量查看和管理多个会话for session in $(tmux ls -F "#{session_name}"); do echo "=== Session: $session ===" tmux list-windows -t $sessiondonetmux 快捷键(默认前缀 Ctrl+B):
| 快捷键 | 功能说明 |
|---|---|
Ctrl+B, d | 分离当前会话 |
Ctrl+B, c | 创建新窗口 |
Ctrl+B, n | 切换到下一个窗口 |
Ctrl+B, p | 切换到上一个窗口 |
Ctrl+B, l | 切换到上次使用的窗口 |
Ctrl+B, w | 列出所有窗口并选择 |
Ctrl+B, & | 关闭当前窗口(需确认) |
Ctrl+B, , | 重命名当前窗口 |
Ctrl+B, " | 竖直分割窗格 |
Ctrl+B, % | 水平分割窗格 |
Ctrl+B, o | 在分割窗格间循环 |
Ctrl+B, x | 关闭当前窗格 |
Ctrl+B, z | 放大/缩小当前窗格 |
Ctrl+B, [ | 进入复制模式(可滚动查看历史) |
Ctrl+B, ] | 粘贴复制的内容 |
Ctrl+B, : | 进入命令模式 |
Ctrl+B, ? | 显示所有快捷键帮助 |
nohup、&、screen、tmux 对比总结:
| 特性 | nohup | & | screen | tmux |
|---|---|---|---|---|
| 简单易用程度 | ★★★★★ | ★★★★★ | ★★★☆☆ | ★★★★☆ |
| 免疫SIGHUP | ✓ | ✗ | ✓ | ✓ |
| 支持多窗口/窗格 | ✗ | ✗ | ✓ | ✓ |
| 支持会话分离/重连 | ✗ | ✗ | ✓ | ✓ |
| 多用户协作 | ✗ | ✗ | ✓ | ✓ |
| 配置灵活性 | ✗ | ✗ | ✓ | ★★★★★ |
| 现代化程度 | ✭ | ✭ | ★★★ | ★★★★☆ |
| 用于长期后台服务 | ★★★★★ | ☆ | ★★★★☆ | ★★★★☆ |
| 用于交互式开发 | ☆ | ✗ | ★★★★☆ | ★★★★★ |
五、端口占用与网络连接(进程的网络资源)
5.1 问题背景
在日常运维工作中,经常会遇到”某个端口已被占用”的问题,导致服务无法启动。此时需要快速定位是哪个进程占用了该端口,然后决定是否杀死它或修改服务端口号。本章介绍三大神器:ss、netstat 和 lsof。
5.2 ss 命令:现代化的网络统计工具
ss (socket statistics) 是新一代的网络连接查看工具,性能比 netstat 更好,功能更强大。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-a / --all | all sockets | 显示所有socket(包括监听和已建立连接) | ss -a |
-l / --listening | listening | 仅显示处于监听状态的socket | ss -l |
-t / --tcp | TCP | 仅显示TCP协议的socket | ss -t |
-u / --udp | UDP | 仅显示UDP协议的socket | ss -u |
-n / --numeric | numeric | 显示IP地址和端口号(不进行DNS反向解析) | ss -n |
-p / --process | process | 显示使用该socket的进程信息 | ss -p |
-e / --extended | extended | 显示扩展信息(如接收缓冲、发送缓冲等) | ss -e |
-m / --memory | memory | 显示内存使用统计 | ss -m |
-i / --info | info | 显示TCP内部信息(如RTO、重传次数等) | ss -i |
-s / --summary | summary | 显示统计摘要而非详细列表 | ss -s |
-H / --no-header | no header | 不显示表头 | ss -H |
-K / --kill | kill | 关闭符合条件的socket(需root权限) | ss -K dst 192.168.1.100 |
--dport <port> | dest port | 按目标端口过滤 | ss -t --dport :8080 |
--sport <port> | source port | 按源端口过滤 | ss -t --sport :8080 |
-A <proto> | protocol family | 指定协议族(inet、inet6、unix等) | ss -A inet |
dst <address> | destination | 按目标地址过滤 | ss dst 192.168.1.100 |
src <address> | source | 按源地址过滤 | ss src 192.168.1.100 |
最常用组合速记:
ss -tlnp # 显示所有监听的TCP端口及其进程(最常用!)ss -tunap # 显示所有TCP和UDP连接及其进程ss -s # 统计摘要ss -t --dport :8080 # 查看占用8080端口的进程模拟输出示例:
# 执行: ss -tlnpState Recv-Q Send-Q Local Address:Port Peer Address:Port ProcessLISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=456,fd=3))LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1200,fd=6))LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1200,fd=7))LISTEN 0 100 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=2000,fd=20))LISTEN 0 128 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=890,fd=6))LISTEN 0 100 0.0.0.0:8080 0.0.0.0:* users:(("java",pid=2234,fd=45))
# 执行: ss -tunapState Recv-Q Send-Q Local Address:Port Peer Address:Port ProcessLISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=456,fd=3))LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1200,fd=6))ESTAB 0 0 192.168.1.100:22 192.168.1.1:54321 users:(("sshd",pid=2048,fd=3))ESTAB 0 0 192.168.1.100:80 192.168.1.50:12345 users:(("nginx",pid=1201,fd=7))TIME_WAIT 0 0 192.168.1.100:8080 192.168.1.51:54322
# 执行: ss -sTCP: 7 ESTABLISHED 2 SYN-SENT 0 CLOSED 0 CLOSEWAIT 0 TIME-WAIT 8 CLOSE-PROXY 0 other 0INET: 7 RECEIVED ACK 2 RECEIVED RST 0 RECEIVED ECN 0 SENT RST 1000 SEND-PROBES 100InSegs: 12500OutSegs: 10200实战应用场景:
# 场景1:查看所有监听的端口及其进程(最常用!)ss -tlnp
# 场景2:查看所有TCP连接及其进程(包括已建立和待连接状态)ss -tunap
# 场景3:查看特定端口被谁占用ss -t --dport :8080 # 查看8080端口ss -t --dport :22 # 查看SSH端口
# 场景4:按照进程ID查找所有网络连接ss -p | grep "pid=2234"
# 场景5:查看UDP监听端口(如DNS、NTP服务)ss -ul
# 场景6:查看某个IP地址的所有连接ss src 192.168.1.100ss dst 192.168.1.200
# 场景7:查看socket统计(内存使用等)ss -s
# 场景8:查看TCP连接状态统计(多少个ESTABLISHED、TIME_WAIT等)ss -t -s
# 场景9:实时监控(每2秒更新一次)watch -n 2 'ss -tlnp'
# 场景10:查找处于TIME_WAIT状态的连接(可能导致端口不可用)ss -t state TIME-WAIT
# 场景11:查看某个用户的所有网络连接ss -p | grep "xiaoying"
# 场景12:输出IPv6监听端口ss -tlnp | grep -i ipv65.3 netstat 命令:经典的网络统计工具
netstat 是传统的网络状态查看工具,在一些较老的Linux系统上仍然常用。虽然 ss 更现代,但 netstat 在某些场景下仍有用处。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-a / --all | all | 显示所有socket | netstat -a |
-l / --listening | listening | 仅显示监听状态 | netstat -l |
-t / --tcp | TCP | 仅显示TCP | netstat -t |
-u / --udp | UDP | 仅显示UDP | netstat -u |
-n / --numeric | numeric | 不进行DNS解析 | netstat -n |
-p / --program | program | 显示关联的进程PID和名称 | netstat -p |
-e / --extend | extend | 显示扩展信息 | netstat -e |
-s / --statistics | statistics | 显示统计汇总 | netstat -s |
-r / --route | route | 显示路由表 | netstat -r |
-i / --interfaces | interfaces | 显示网络接口统计 | netstat -i |
-g / --group | multicast | 显示多播组 | netstat -g |
-M / --masquerade | masquerade | 显示伪装连接 | netstat -M |
-c / --continuous | continuous | 持续更新输出(每秒刷新) | netstat -c |
最常用组合速记:
netstat -tlnp # 显示所有监听的TCP端口及进程netstat -tunap # 显示所有TCP和UDP连接netstat -s # 统计摘要netstat -r # 显示路由表模拟输出示例:
# 执行: netstat -tlnpProto Recv-Q Send-Q Local Address Foreign Address State PID/Program nametcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 456/sshdtcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1200/nginxtcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 1200/nginxtcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 2000/mysqldtcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 890/postgrestcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 2234/java
# 执行: netstat -sIp: Forwarding: 0 12500 total packets received 0 forwarded 0 incoming packets discarded 12500 incoming packets delivered 10200 requests sent out...Tcp: 200 active connections openings 150 passive connection openings 50 failed connection attempts ...实战应用场景:
# 场景1:查看所有监听的TCP端口netstat -tlnp
# 场景2:查看所有已建立的TCP连接netstat -tp | grep ESTABLISHED
# 场景3:查看路由表netstat -r
# 场景4:显示网络接口统计netstat -i
# 场景5:统计TCP状态分布netstat -an | grep -i tcp | awk '{print $NF}' | sort | uniq -c | sort -rn
# 场景6:监控实时网络连接(每秒更新)netstat -c
# 场景7:查看某个端口的所有连接netstat -tulnp | grep :8080
# 场景8:查看处于TIME_WAIT状态的连接数netstat -an | grep TIME_WAIT | wc -l
# 场景9:显示全部网络统计信息netstat -s
# 场景10:查看某个用户的网络连接netstat -tulnp | grep username5.4 lsof 命令:查看进程打开的文件和网络连接
lsof (list open files) 是最强大的文件和网络连接查看工具,可以显示进程打开的所有文件、socket等。
参数讲解表:
| 参数 | 全称 | 用途说明 | 示例 |
|---|---|---|---|
-i | internet | 显示网络连接 | lsof -i |
-i:<port> | port | 显示指定端口的连接 | lsof -i:8080 |
-i<protocol> | protocol | 指定协议(TCP、UDP) | lsof -iTCP -sTCP:LISTEN |
-p <pid> | process | 显示指定PID的进程打开的文件 | lsof -p 2234 |
-u <user> | user | 显示指定用户的进程打开的文件 | lsof -u xiaoying |
-c <command> | command | 显示指定命令名的进程打开的文件 | lsof -c nginx |
-d <fd> | file descriptor | 显示指定文件描述符 | lsof -d 3,4,5 |
-a | and | 逻辑AND组合多个条件 | lsof -i:8080 -a -p 2234 |
+d <dir> | directory | 显示某个目录下被打开的文件 | lsof +d /var/log |
-n / -P | numeric | 不进行DNS/服务名解析 | lsof -n -i |
-s <state> | state | 按状态过滤 | lsof -i -s TCP:LISTEN |
-t | terse | 仅输出PID(简洁模式) | lsof -t -i:8080 |
+L | lost | 显示已删除但仍被进程占用的文件 | lsof +L |
+D <dir> | recursive | 递归显示目录内被打开的文件 | lsof +D /var |
最常用组合速记:
lsof -i:8080 # 查看占用8080端口的进程lsof -i TCP:LISTEN # 显示所有监听的TCP端口lsof -p 2234 # 查看PID为2234的进程打开的所有文件lsof -u xiaoying # 查看用户xiaoying打开的所有文件模拟输出示例:
# 执行: lsof -i:8080COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEjava 2234 xiaoying 45u IPv4 0x12345678 0t0 TCP *:8080 (LISTEN)curl 12345 xiaoying 15u IPv4 0x87654321 0t0 TCP 192.168.1.100:54321->10.0.0.1:8080 (ESTABLISHED)
# 执行: lsof -i TCP:LISTENCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsshd 456 root 3u IPv4 0x11111111 0t0 TCP *:22 (LISTEN)nginx 1200 root 6u IPv4 0x22222222 0t0 TCP *:80 (LISTEN)nginx 1200 root 7u IPv4 0x33333333 0t0 TCP *:443 (LISTEN)mysqld 2000 mysql 20u IPv4 0x44444444 0t0 TCP 127.0.0.1:3306 (LISTEN)postgres 890 post 6u IPv4 0x55555555 0t0 TCP 127.0.0.1:5432 (LISTEN)java 2234 xiao 45u IPv4 0x66666666 0t0 TCP *:8080 (LISTEN)
# 执行: lsof -p 2234COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEjava 2234 xiaoying cwd DIR 0,18 4096 13107203 /home/xiaoying/myappjava 2234 xiaoying txt REG 0,18 5234567 13107456 /usr/bin/javajava 2234 xiaoying mem REG 0,18 12345678 13108000 /usr/lib/jvm/java/lib/server/libjvm.sojava 2234 xiaoying 0u CHR 1,3 0t0 1026 /dev/nulljava 2234 xiaoying 1u REG 0,18 1234567 13109000 /var/log/app.logjava 2234 xiaoying 2u REG 0,18 1234567 13109000 /var/log/app.logjava 2234 xiaoying 3u IPv4 0x12345678 0t0 TCP *:8080 (LISTEN)java 2234 xiaoying 10u unix 0xabcdef12 0t0 FILE /tmp/java-socket...输出字段详解:
| 字段 | 示例 | 含义 |
|---|---|---|
COMMAND | java, nginx | 进程的命令名 |
PID | 2234, 1200 | 进程ID |
USER | xiaoying, root | 进程所属用户 |
FD | 3, 45u, cwd | 文件描述符(u表示读写,r表示读,w表示写;cwd表示当前工作目录) |
TYPE | IPv4, REG, DIR, CHR | 文件类型(IPv4/IPv6网络、普通文件、目录、字符设备等) |
DEVICE | 0,18, 0x123 | 设备号 |
SIZE/OFF | 4096, 0t0 | 文件大小或偏移 |
NODE | /dev/null, TCP *:8080 | inode号或网络信息 |
NAME | /home/xiaoying/myapp | 文件或网络连接的完整名称 |
实战应用场景:
# 场景1:查看占用8080端口的进程(最常用!)lsof -i:8080
# 场景2:查看所有监听的TCP端口lsof -i TCP:LISTEN
# 场景3:查看所有已建立的TCP连接lsof -i TCP -s TCP:ESTABLISHED
# 场景4:查看某个进程打开的所有文件和网络连接lsof -p 2234
# 场景5:查看某个用户的所有打开文件和网络连接lsof -u xiaoying
# 场景6:查看某个命令关联的进程打开的文件lsof -c nginx
# 场景7:查看某个特定文件被哪些进程打开lsof /var/log/app.log
# 场景8:仅输出占用8080端口的进程PID(用于管道)lsof -t -i:8080
# 场景9:查看已删除但仍被占用的文件(排查磁盘空间泄漏)lsof +L 1
# 场景10:查看某个目录被打开的文件lsof +d /var/log
# 场景11:实时监控网络连接(每2秒更新)watch -n 2 'lsof -i TCP:LISTEN'
# 场景12:查看占用某个端口的进程并直接杀死kill -9 $(lsof -t -i:8080)
# 场景13:统计进程打开的文件描述符数量(用于排查FD泄漏)lsof -p 2234 | wc -l
# 场景14:查看最多打开文件数的进程lsof | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# 场景15:查看网络连接统计(不同状态的连接数)lsof -i -s TCP:LISTEN,ESTABLISHED,TIME_WAIT5.5 三大工具对比总结
| 特性 | ss | netstat | lsof |
|---|---|---|---|
| 显示监听端口 | ✓ 推荐 | ✓ | ✓ |
| 显示已建立连接 | ✓ | ✓ | ✓ |
| 显示进程信息 | ✓ | ✓ | ✓ |
| 按端口过滤 | ✓ | ✗ | ✓ 推荐 |
| 按进程过滤 | ✗ | ✗ | ✓ 推荐 |
| 显示打开的文件 | ✗ | ✗ | ✓ 仅此工具 |
| 性能 | ★★★★★ (最快) | ★★★☆☆ | ★★☆☆☆ |
| 现代化程度 | ★★★★★ | ★★☆☆☆ | ★★★☆☆ |
| 在新系统推荐度 | ★★★★★ | ★★☆☆☆ | ★★★★☆ |
5.6 快速定位端口占用的完整流程
#!/bin/bash# 快速查找占用指定端口的进程并处理
PORT=${1:-8080}
echo "=== 查找占用端口 $PORT 的进程 ==="
# 方法1:使用lsof(推荐,最直观)echo -e "\n【方法1:使用lsof】"lsof -i :$PORT
# 方法2:使用ssecho -e "\n【方法2:使用ss】"ss -tlnp | grep :$PORT
# 方法3:使用netstatecho -e "\n【方法3:使用netstat】"netstat -tulnp | grep :$PORT
# 获取PID并交互式处理echo -e "\n=== 处理选项 ==="PID=$(lsof -t -i:$PORT)
if [ -z "$PID" ]; then echo "❌ 未找到占用端口 $PORT 的进程" exit 1fi
echo "✓ 找到进程: PID=$PID"ps -p $PID
echo -e "\n选择操作:"echo "1) 查看进程详细信息"echo "2) 正常终止进程 (kill -15)"echo "3) 强制杀死进程 (kill -9)"echo "4) 不做处理"
read -p "请输入选择 [1-4]: " choice
case $choice in 1) lsof -p $PID ;; 2) kill -15 $PID echo "已发送SIGTERM信号,等待3秒..." sleep 3 if ps -p $PID > /dev/null; then echo "⚠ 进程仍在运行,尝试强制杀死" kill -9 $PID fi echo "✓ 进程已终止" ;; 3) kill -9 $PID echo "✓ 进程已强制杀死" ;; 4) echo "未进行任何操作" ;; *) echo "❌ 无效选择" exit 1 ;;esac六、排查与干预最佳实践
[!TIP] 标准化操作链路
- 生命周期敬畏:永远优先使用
15号信号请求进程自行退位,给它保留体面的权力。- 僵尸巡检制度:通过
ps aux | grep Z搭配定时巡检进行存量清零,不要让垃圾堆砌成为服务假死的暗雷。- 批量裁决效率:当你面对大规模的并行任务池且需要重置时,使用
pkill可以杜绝低效的查阅 PID 循环。- CPU过载救援SOP:
- 敲击
top进入或使用htop进行实时观测。- 视线锁定首行
load average,判断是否超过CPU核心数。- 键入
P或M(按CPU或内存排序),找出罪魁祸首。- 若眼见
%wa数值飙升(超过15%),请立刻转移视线去重点排查磁盘IO瓶颈。- 网络连接排查SOP:
- 使用
ss -tlnp快速查看所有监听端口。- 使用
lsof -i:PORT定位占用特定端口的进程。- 使用
lsof -p PID查看进程打开的所有文件和连接。- 对于异常连接,先排查防火墙规则,再考虑杀死进程。
6.1 典型场景实战演练
场景1:启动服务时提示”Address already in use”
# 问题:Nginx无法启动,提示8080端口被占用
# 第1步:查找占用端口的进程lsof -i:8080# 输出: java ... TCP *:8080 (LISTEN)
# 第2步:查看该进程的详细信息ps -p 2234 -o pid,ppid,user,%cpu,%mem,comm,args# 输出: PID=2234, 占用内存3.5%, 是之前启动的java应用
# 第3步:决策:如果是旧进程则杀死,如果还需要则改变服务端口kill -15 2234sleep 2# 验证是否成功lsof -i:8080# 无输出说明成功,可启动Nginx了场景2:系统负载过高,CPU接近100%
# 第1步:进入htop查看实时进程htop
# 第2步:按P键按CPU使用率排序,找到占用最多的进程# 发现: java进程占用55% CPU
# 第3步:查看该java进程的详细信息和网络连接lsof -p 2234 | head -20
# 第4步:决策分析# - 如果是业务应用,查看是否有死循环或内存溢出# - 如果是异常进程,直接kill -9# - 如果需要保留,考虑优化代码或增加资源
kill -15 2234场景3:内存泄漏导致内存持续增长
# 第1步:使用top或htop监控内存趋势watch -n 5 'ps aux | grep java | head -5'
# 第2步:查看进程打开的文件(可能文件描述符泄漏)lsof -p 2234 | wc -l# 如果数字远大于正常值(如>1000),则可能是FD泄漏
# 第3步:查看已删除但被进程占用的文件lsof -p 2234 | grep deleted# 若有输出,说明磁盘空间被泄漏占用
# 第4步:决策:重启该进程释放资源,同时排查代码问题systemctl restart myapp场景4:终端SSH连接慢,响应迟缓
# 第1步:检查网络连接状态ss -tunap | grep ESTABLISHED | wc -l# 若数值很大(如>10000),说明有大量连接堆积
# 第2步:查看TIME_WAIT状态的连接ss -tan state TIME-WAIT | wc -l
# 第3步:查找占用SSH端口的进程ss -tlnp | grep :22lsof -i:22
# 第4步:检查是否有异常的大量SSH连接尝试ss -tan | grep :22 | wc -l
# 第5步:如果是DDoS攻击,可以:# - 限制并发连接数(iptables规则)# - 关闭不必要的服务# - 分析日志找出攻击源场景5:守护进程(如Nginx)在后台运行但无法正常重启
# 第1步:查看Nginx相关进程ps aux | grep nginxpgrep -a nginx
# 第2步:强制终止所有nginx进程pkill -9 nginx
# 第3步:等待一秒,确保进程完全退出sleep 1
# 第4步:验证进程已退出pgrep nginx # 无输出说明成功
# 第5步:重新启动nginxsystemctl start nginx# 或nginx -s start
# 第6步:验证启动成功lsof -i:80ss -tlnp | grep nginx总结
本文深入讲解了Linux进程管理的核心技能:
- 进程基础:理解进程分类、PID概念、孤儿进程与僵尸进程的原理
- 查看工具:掌握
ps、pstree、top、htop等进程查看命令 - 控制命令:灵活运用
kill、pkill、killall等进程控制命令 - 快速定位:使用
pgrep和pidof快速查找进程 - 后台运行:理解
nohup、&、screen、tmux等后台管理工具的差异和应用 - 网络诊断:掌握
ss、netstat、lsof等端口和网络连接查看工具 - 最佳实践:遵循”优先级递进、体面优先、数据安全第一”的运维哲学
掌握这些技能后,你将能够:
- 快速定位和解决进程相关的各类问题
- 优雅地管理后台进程和长期运行的任务
- 诊断端口占用和网络连接问题
- 在生产环境中安全、高效地进行进程控制
记住:在Linux系统中,进程是一切的基础。掌握进程管理就掌握了系统运维的核心。