Linux 进程管理
Linux 进程管理
目录
- 进程与线程的基本概念
- 进程查看:ps / top / htop
- 进程状态:R / S / D / Z / T
- 看懂 top 输出
- 结束进程:kill / pkill 与信号
- 前台 / 后台作业控制
- systemd 入门:systemctl 与开机自启
- 进程优先级:nice / renice
- 僵尸进程与孤儿进程
- 总结与练习
一、进程与线程的基本概念
进程(Process) 是正在运行的程序的一个实例,是系统分配资源的基本单位。程序是静态的文件,进程是动态的运行实体。
关键概念:
- PID(Process ID):进程的唯一编号。
- PPID(Parent PID):父进程的 PID。每个进程都由另一个进程(父进程)创建。
- 进程与线程:一个进程可以包含多个线程(Thread),线程是进程内并行执行的最小单位。
查看当前 shell 的进程信息:
echo $$ # 当前 shell 的 PID
echo $PPID # 当前 shell 的父进程 PID
pstree # 以树形显示进程父子关系
pstree -p # 同时显示 PID
进程树:所有进程的最顶层是 PID 为 1 的进程(Rocky/RHEL 上通常是 systemd),它负责管理整个系统。
参考:
man 7 process、菜鸟教程 - Linux 进程管理
二、进程查看:ps / top / htop
2.1 ps —— 快照查看进程
ps(process status)显示某个时刻的进程快照。常用组合:
ps # 只显示当前终端自己的进程
ps -ef # ★显示所有进程(-e all,-f 完整格式)
ps aux # ★另一种常用写法(a 所有终端,u 用户格式,x 无终端进程)
ps -ef | grep nginx # 配合 grep 查找指定进程
ps -fp <pid> # 查看指定 PID 的进程
ps -u username # 查看某用户的进程
ps aux 的输出列:
| 列 | 含义 |
|---|---|
| USER | 运行该进程的用户 |
| PID | 进程号 |
| %CPU | CPU 占用率 |
| %MEM | 内存占用率 |
| VSZ | 虚拟内存大小(KB) |
| RSS | 实际常驻内存大小(KB) |
| TTY | 关联的终端(? 表示无终端/后台) |
| STAT | 进程状态(见第三章) |
| START | 启动时间 |
| TIME | 累计占用 CPU 时间 |
| COMMAND | 启动命令 |
2.2 top —— 实时动态查看
top 实时刷新显示进程和系统资源,是监控 CPU/内存的主力工具。
top # 进入实时监控界面
top -d 2 # 每 2 秒刷新一次
top -p <pid> # 只监控指定进程
top -u username # 只看某用户进程
进入 top 后的常用按键:
| 按键 | 作用 |
|---|---|
| q | 退出 |
| P | 按 CPU 占用排序(默认) |
| M | 按内存占用排序 |
| k | 杀掉某个进程(会提示输入 PID) |
| r | 调整某个进程的优先级(renice) |
| 1 | 展开/折叠多核 CPU 显示 |
| h | 帮助 |
详细解析见第四章。
2.3 htop —— 更友好的进程查看
htop 是 top 的增强版,带彩色界面、可鼠标操作,需单独安装:
sudo dnf install -y htop # Rocky 安装
htop
- 彩色显示、上下左右/鼠标可操作。
- 直接按 F9 杀进程、F6 排序、F7/F8 调整优先级,更直观。
- Ubuntu/Debian 用
sudo apt install htop。
参考:
man 1 ps、man 1 top、man 1 htop
三、进程状态:R / S / D / Z / T
在 ps 的 STAT 列和 top 的 S 列会显示进程状态,常见如下:
| 状态 | 名称 | 含义 |
|---|---|---|
| R | Running | 正在运行或处于可运行队列 |
| S | Sleeping(可中断) | 正在睡眠/等待,可被信号唤醒(最常见) |
| D | Uninterruptible sleep | 不可中断睡眠(通常在等待磁盘 I/O),不能用 kill 杀掉 |
| Z | Zombie | 僵尸进程(进程已结束但未被父进程回收) |
| T | Stopped | 已停止/挂起(如被 Ctrl+Z 或 SIGSTOP 挂起) |
| I | Idle | 空闲的内核线程(新内核有) |
STAT 列还可能带附加符号:
| 符号 | 含义 |
|---|---|
+ |
在前台进程组中 |
< |
高优先级 |
N |
低优先级 |
s |
会话领导者(session leader) |
l |
多线程进程 |
示例:S+ 表示"可中断睡眠 + 前台";Z 表示僵尸进程。
僵尸进程(Z) 会在第九章详细讲解。
参考:
man 1 ps(STATE 部分)、man ps中的PROCESS STATE CODES
四、看懂 top 输出
top 界面上半部分是系统总览,下半部分是进程列表。
4.1 第一行:系统运行时间与负载
top - 10:20:30 up 3 days, 2:15, 3 users, load average: 0.30, 0.45, 0.52
10:20:30:当前时间。up 3 days, 2:15:系统已运行 3 天 2 小时 15 分。3 users:当前登录用户数。load average: 0.30, 0.45, 0.52:系统负载(过去 1 分钟、5 分钟、15 分钟的平均运行队列长度)。
负载怎么看:负载值约等于"在排队等待 CPU 的进程数"。通常负载 < CPU 核数表示正常,远大于核数表示 CPU 过载。例如 4 核机器负载接近 4 或以上需关注。
4.2 第二行:进程与线程数
Tasks: 220 total, 2 running, 218 sleeping, 0 stopped, 0 zombie
total:总进程数;running:运行中;sleeping:睡眠中;stopped:已停止;zombie:僵尸进程。
注意 zombie 这一项:若持续有僵尸进程且数量增长,需排查(见第九章)。
4.3 第三、四行:CPU 与内存使用
%Cpu(s): 10.0 us, 5.0 sy, 0.0 ni, 85.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 7840.0 total, 3000.0 free, 3200.0 used, 1640.0 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used, 3000.0 avail Mem
CPU 各项(us/sy/ni/id/wa/hi/si/st):
| 项 | 含义 |
|---|---|
| us | 用户态 CPU 时间占比 |
| sy | 系统态(内核)CPU 时间占比 |
| ni | 被 nice 调整过优先级的进程占用的 CPU |
| id | 空闲 CPU 占比(越大越空闲) |
| wa | 等待 I/O 的 CPU 占比(过高说明磁盘/IO 慢) |
| hi / si | 硬件 / 软件中断 |
| st | 被虚拟化超卖偷走的 CPU(虚拟机) |
内存(Mem/Swap):total 总量、free 空闲、used 已用、buff/cache 缓存、avail Mem 可用内存。
注意:Linux 会把空闲内存用作缓存(buff/cache),所以"used"看着高不代表内存不足,要看
avail Mem(真正可用)。
4.4 进程列表各列
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1234 root 20 0 162152 7500 5680 S 1.3 0.1 0:01.25 httpd
| 列 | 含义 |
|---|---|
| PID | 进程号 |
| USER | 用户 |
| PR | 内核调度优先级(nice 值映射,20=普通) |
| NI | nice 值(-20~19,越低越优先) |
| VIRT | 虚拟内存大小 |
| RES | 实际物理内存 |
| SHR | 共享内存 |
| S | 状态(见第三章) |
| %CPU | CPU 占用率 |
| %MEM | 内存占用率 |
| TIME+ | 累计 CPU 时间 |
| COMMAND | 命令 |
参考:
man 1 top、菜鸟教程 - Linux top 命令
五、结束进程:kill / pkill 与信号
5.1 信号(Signal)是什么
信号是系统向进程发送的异步通知,用于让进程做出某种响应(如退出)。进程管理中的"杀进程"本质就是发送信号。
查看所有信号:kill -l。
5.2 常用信号
| 信号 | 编号 | 含义 | 默认行为 |
|---|---|---|---|
| SIGTERM | 15 | 终止信号(默认) | 让进程优雅退出,进程可捕获处理 |
| SIGKILL | 9 | 强制终止 | 立即杀死,进程无法捕获/忽略 |
| SIGINT | 2 | 中断(Ctrl+C 触发) | 终止前台进程 |
| SIGSTOP | 19 | 停止(挂起) | 暂停进程,进程无法捕获 |
| SIGCONT | 18 | 继续 | 恢复被 SIGSTOP 暂停的进程 |
| SIGHUP | 1 | 挂断 | 终端断开时发送,常导致进程退出 |
SIGTERM vs SIGKILL(关键区别):
- SIGTERM(15):给进程"体面退出的机会",进程可以保存状态、清理资源后再退出。优先使用。
- SIGKILL(9):强制立刻杀掉,进程无法做任何清理,可能造成数据丢失或留下残留。仅在 SIGTERM 无效时才用。
5.3 kill —— 按 PID 发信号
kill <pid> # 默认发 SIGTERM(15)
kill -15 <pid> # 显式 SIGTERM
kill -9 <pid> # SIGKILL 强制杀
kill -SIGTERM <pid> # 用名称
kill -l # 列出所有信号
# 查找并结束某进程
ps -ef | grep httpd
kill 1234 # 先优雅终止
kill -9 1234 # 无效才强制
5.4 pkill —— 按名称发信号
pkill httpd # 结束所有名字含 httpd 的进程(发 SIGTERM)
pkill -9 httpd # 强制结束
pkill -u username # 结束某用户的所有进程
pkill -f "pattern" # 按完整命令行匹配
还有
killall 名称也可按名字结束(用法类似 pkill)。
杀进程的建议顺序:先用 SIGTERM(kill),不行再用 SIGKILL(kill -9)。不要一上来就 -9。
参考:
man 1 kill、man 1 pkill、man 7 signal
六、前台 / 后台作业控制
6.1 前台 vs 后台
- 前台(Foreground):进程占用当前终端,命令执行完才能输入下一条(默认)。
- 后台(Background):进程在后台运行,终端可以继续输入其他命令。
6.2 把进程放到后台:&
command & # 在命令后加 & 让其在后台运行
sleep 100 & # 示例:后台运行一个睡眠 100 秒的进程
6.3 作业控制:jobs / fg / bg
jobs # 查看当前终端的后台作业(带作业号 [1] [2])
jobs -l # 同时显示 PID
fg %1 # 把作业 1 调回前台(foreground)
bg %1 # 把暂停的作业 1 放到后台继续跑
kill %1 # 按作业号结束
%1中%后面是作业号(jobs 显示的 [1]),不是 PID。
6.4 Ctrl+C 与 Ctrl+Z(关键区别)
| 按键 | 发送信号 | 作用 |
|---|---|---|
| Ctrl+C | SIGINT(2) | 中断:终止当前前台进程 |
| Ctrl+Z | SIGTSTP(20) | 挂起/暂停:把当前前台进程暂停(不终止),回到 shell |
示例:运行 sleep 100,按 Ctrl+Z 会暂停它并显示作业号,然后用 bg 放后台或 fg 调回前台。
sleep 100
# 按 Ctrl+Z → [1]+ Stopped sleep 100
jobs # 看到作业 1 已停止
bg %1 # 放到后台继续
jobs # 看到 [1]+ Running
6.5 nohup —— 关闭终端也不中断
普通后台进程(&)在关闭终端/退出 shell 时可能被 SIGHUP 信号终止。用 nohup(no hang up)可以让进程忽略 SIGHUP,即使退出终端也继续运行。
nohup command & # 后台运行并忽略挂断信号
nohup myapp > app.log 2>&1 & # 常见:输出重定向到日志,后台运行
nohup ./start.sh & # 服务器上长驻脚本常用
nohup默认把输出写到nohup.out,可用>重定向到指定文件。- 适合需要在登出后仍持续运行的任务(如启动服务、长时间任务)。
参考:
man 1 bash(Job Control)、man 1 nohup、菜鸟教程 - Linux 进程管理
七、systemd 入门:systemctl 与开机自启
systemd 是现代 Linux(RHEL/Rocky、Ubuntu 等)的系统与服务管理器,是 PID 1 进程。它管理系统的所有服务、启动项。
7.1 单元(Unit)
systemd 管理的对象叫单元(Unit),常见类型:
| 单元类型 | 后缀 | 说明 |
|---|---|---|
| 服务 | .service |
服务/守护进程 |
| 挂载点 | .mount |
文件系统挂载 |
| 套接字 | .socket |
网络/本地套接字 |
| 目标 | .target |
一组单元的集合(如 multi-user.target) |
| 定时器 | .timer |
定时任务 |
7.2 systemctl 常用操作(管理服务)
sudo systemctl start httpd # 启动服务
sudo systemctl stop httpd # 停止服务
sudo systemctl restart httpd # 重启服务
sudo systemctl reload httpd # 重载配置(不中断服务)
sudo systemctl status httpd # 查看服务状态
sudo systemctl enable httpd # ★开机自启
sudo systemctl disable httpd # 取消开机自启
sudo systemctl enable --now httpd # 设置开机自启并立即启动
systemctl is-active httpd # 是否运行中
systemctl is-enabled httpd # 是否开机自启
systemctl list-units --type=service # 列出所有服务单元
systemctl list-unit-files --type=service # 列出所有服务及是否启用
enable vs start 区别:
start只立即启动本次生效;enable设置开机自启。要让服务"现在运行 + 开机自启",两者都要(或enable --now)。
7.3 查看服务日志
journalctl -u httpd # 查看某服务的日志
journalctl -u httpd -f # 实时跟踪(类似 tail -f)
journalctl -u httpd --since today # 今天的日志
journalctl是 systemd 的日志查看工具,-u指定单元。
参考:
man 1 systemctl、man 5 systemd.unit、Red Hat - 使用 systemd 管理服务、菜鸟教程 - Linux systemctl
八、进程优先级:nice / renice
8.1 nice 值是什么
- nice 值范围 -20 ~ 19,数值越小优先级越高。
- 默认 nice 值是 0。
- 只有 root 能设置负值(提高优先级);普通用户只能设正值(降低自己进程的优先级)。
8.2 nice —— 启动时指定优先级
nice -n 10 command # 以 nice=10 启动 command(降低优先级)
nice -n -5 command # 以 nice=-5 启动(提高优先级,需 root)
sudo nice -n -10 myapp
8.3 renice —— 修改已运行进程的优先级
renice -n 5 -p <pid> # 把 pid 进程 nice 调整为 5
sudo renice -n -5 -p <pid> # root 提高优先级
renice -n 5 -u username # 调整某用户所有进程
查看进程优先级:top 中的 NI 列,或 ps -o pid,nice,cmd。
ps -o pid,nice,comm -p <pid> # 查看指定进程的 nice 值
什么时候用:让"不着急"的后台任务降低优先级(给前台交互让出 CPU),或给关键任务提高优先级。
参考:
man 1 nice、man 1 renice
九、僵尸进程与孤儿进程
9.1 僵尸进程(Zombie)
僵尸进程(状态 Z):进程已经结束,但由于某种原因父进程没有回收它的退出状态,于是它在进程表中保留一个"尸体"记录。
- 僵尸进程不再占用 CPU 和内存,但会占用一个 PID 和进程表项。
- 少量僵尸通常无害,但如果大量堆积,会耗尽 PID 资源。
- 僵尸进程无法用 kill 杀掉(它已经死了),只能让父进程回收(或杀掉父进程,由 init/systemd 接管回收)。
产生原因:父进程没有调用 wait() 系统调用回收子进程的退出状态(常见于编程 bug)。
# 查看僵尸进程(状态列为 Z)
ps aux | grep defunct
top # 第二行 Tasks 里看 zombie 数量
处理僵尸进程:
# 找到僵尸进程的父进程
ps -o pid,ppid,stat,cmd -p <zombie_pid>
# 僵尸进程已无法直接 kill,尝试:
# 1. 让父进程回收:结束父进程(父进程结束后由 systemd/init 接管回收)
# 2. 若父进程是 init 会自己回收;顽固僵尸通常需要重启相关服务或重启系统
9.2 孤儿进程(Orphan)
- 孤儿进程:父进程先于子进程结束,子进程被"收养"为 PID 1(systemd/init)的子进程。
- 孤儿进程会被
init/systemd收养并负责回收,不是问题。 - 与僵尸不同,孤儿进程还在正常运行,只是换了个父进程。
一句话区分:
- 僵尸:子进程死了,父进程没回收 → 残留记录。
- 孤儿:父进程先死,子进程还活着 → 被 init 收养。
参考:
man 7 signal、Red Hat - 使用 systemd 管理服务
十、总结与练习
10.1 核心速查
| 需求 | 命令 |
|---|---|
| 查看所有进程 | ps -ef / ps aux |
| 实时监控 | top / htop |
| 进程树 | pstree -p |
| 优雅结束进程 | kill <pid> |
| 强制结束进程 | kill -9 <pid> |
| 按名称结束 | pkill 名称 |
| 后台运行 | command & |
| 查看作业 | jobs |
| 调回前台 / 放后台 | fg %1 / bg %1 |
| 挂起 / 中断 | Ctrl+Z / Ctrl+C |
| 登出后继续运行 | nohup command & |
| 启动/停止服务 | sudo systemctl start/stop 服务 |
| 开机自启 | sudo systemctl enable 服务 |
| 查看服务日志 | journalctl -u 服务 |
| 设置优先级 | nice -n / renice -n |
| 查看僵尸进程 | `ps aux |
10.2 动手练习建议
# 1. 查看进程
ps -ef | head
top
# 2. 后台与作业控制
sleep 300 &
sleep 200
# 按 Ctrl+Z 挂起
jobs
bg %1; fg %1
# 3. 结束进程
sleep 500 &
echo $! # 上一条后台进程的 PID
kill <那个PID>
# 4. nohup 长驻
nohup sleep 600 > /dev/null 2>&1 &
# 5. systemd 服务
sudo systemctl status sshd
systemctl list-unit-files --type=service | head
# 6. 优先级
ps -o pid,nice,comm -p $$
nice -n 10 sleep 100 &
renice -n 5 -p $$
# 7. 查看僵尸
ps aux | grep -c defunct
提示:练习请在虚拟机(如 Rocky Linux)中进行。
kill、systemctl、renice等命令需注意权限(root 可操作所有进程)。
参考资料
- man 手册:
man 1 ps、man 1 top、man 1 htop、man 1 kill、man 1 pkill、man 7 signal、man 1 bash(Job Control)、man 1 nohup、man 1 systemctl、man 5 systemd.unit、man 1 nice、man 1 renice、man 1 journalctl - Red Hat 官方文档 - 使用 systemd 管理服务:https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_basic_system_settings/managing-services-with-systemd_configuring-basic-system-settings
- Rocky Linux 官方文档 - 进程管理:https://docs.rockylinux.org/books/admin_guide/08-process/
- 菜鸟教程 - Linux 进程管理:https://www.runoob.com/linux/linux-process-manage.html