引言
进程是 Linux 一切运行活动的载体。无论是排查 CPU 100%、定位内存泄漏,还是管理常驻服务,都绕不开对进程模型的准确理解。本文从进程的生命周期讲起,系统覆盖进程查看(ps/top/htop)、信号与 kill、前后台任务、systemd 服务管理,再到 vmstat/iostat 资源监控——一条从「看懂进程」到「管好服务」的完整链路。
前置:熟悉基本命令行。进程的底层原理(PCB、调度)可参考 [[os]] 专题。
目录
- 1. 进程模型与生命周期
- 2. ps:进程快照查看
- 3. top/htop:实时进程监控
- 4. 信号与 kill:进程控制
- 5. 前后台任务与 nohup
- 6. systemd 服务管理
- 7. vmstat/iostat:系统资源监控
- 8. 常见故障排查场景
- 9. 总结:进程管理的思维框架
- 延伸阅读
1. 进程模型与生命周期
1.1 进程 vs 线程
| 概念 | 定义 | 关系 |
|---|---|---|
| 进程(Process) | 运行中的程序实例,拥有独立地址空间 | 一个进程可含多个线程 |
| 线程(Thread) | 进程内的执行单元,共享地址空间 | Linux 中线程是轻量级进程(LWP) |
1.2 生命周期状态
fork()/exec() -> Running(运行)<-> Ready(就绪)
Running -> Sleeping(睡眠)/Stopped(暂停)
Running -> Zombie(僵尸,已退出但父进程未回收)
Zombie -> 父进程 wait() 回收 -> 消亡
1.3 关键命令
# 查看当前 shell 的进程树
pstree -p
# 查看进程父子的 PID/PPID
ps -ef
# 查看指定进程的线程
ps -T -p <pid>
2. ps:进程快照查看
2.1 常用组合
# 全部进程,完整格式(最常用)
ps -ef
# 按 CPU 排序,仅 10 条
ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%cpu | head -10
# 树状显示进程关系
ps -ef --forest
2.2 输出列解读
| 列 | 含义 |
|---|---|
| PID | 进程号 |
| PPID | 父进程号 |
| %CPU / %MEM | CPU 占用百分比 / 内存占用百分比 |
| STAT | 状态(S=sleep, R=running, Z=zombie, T=stopped) |
| TIME | 累计 CPU 时间 |
| CMD | 启动命令 |
2.3 查找特定进程
# 按名字找 PID
pgrep nginx
# 更精确(全命令匹配)
pgrep -f "java -jar app.jar"
# 找到 PID 后查看详情
ps -p <pid> -f
3. top/htop:实时进程监控
3.1 top 核心操作
top
# 交互键:
# P - 按 CPU 排序 M - 按内存排序
# k - 杀掉进程 r - renice 调整优先级
# 1 - 查看每核负载 q - 退出
3.2 top 输出解读
load average: 0.15, 0.20, 0.30 # 1/5/15 分钟平均负载
%Cpu(s): 2.5 us, 1.0 sy, 0.0 ni, 95.9 id
KiB Mem : 15938 total, 8234 free # 内存总量/空闲
3.3 htop:更友好的增强版
# 安装后使用(更直观,支持滚动/搜索/树形)
sudo apt install htop
htop
# F5 树形视图,F6 排序,F9 杀进程
| 工具 | 优势 | 适用 |
|---|---|---|
| top | 系统自带 | 快速查看 |
| htop | 交互丰富、树形 | 日常运维 |
4. 信号与 kill:进程控制
4.1 常用信号
| 信号 | 编号 | 行为 | 用途 |
|---|---|---|---|
| SIGTERM | 15 | 正常终止(可捕获) | 优雅停止,默认推荐 |
| SIGKILL | 9 | 强制终止(不可捕获) | 进程卡死时兜底 |
| SIGHUP | 1 | 终端挂断 | 重载配置(nginx -s reload) |
| SIGINT | 2 | 中断(Ctrl+C) | 交互式中断 |
| SIGSTOP | 19 | 暂停(不可捕获) | 冻结进程 |
| SIGCONT | 18 | 继续 | 恢复暂停进程 |
4.2 kill 实战
# 正常终止(等进程自己退出)
kill <pid>
kill -15 <pid>
# 强制终止(对付无响应的进程)
kill -9 <pid>
# 按名字杀
pkill -9 nginx
killall -9 java
4.3 优雅停服务的顺序
1. 先发 SIGTERM(-15),给进程时间做清理/持久化
2. 等待 N 秒(通常 5-10s)
3. 仍存活则发 SIGKILL(-9)兜底
5. 前后台任务与 nohup
5.1 前后台切换
# 前台运行
./app
# 后台运行
./app &
# 查看后台任务
jobs -l
# 把后台任务调回前台
fg %1
# 把前台任务挂起并转后台
# Ctrl+Z 挂起 -> jobs 查看 -> bg %1 转后台继续
5.2 nohup:脱离终端运行
# 关闭终端后仍运行,输出写文件
nohup ./app > app.log 2>&1 &
# 查看输出的进程
tail -f app.log
5.3 防止误杀
# 脱离终端 + 忽略 HUP 信号
setsid ./app &
# 或使用 tmux/screen 会话
tmux new -s app
tmux detach # Ctrl+b d
tmux attach -t app
6. systemd 服务管理
6.1 服务单元基本操作
# 启停/重启
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl reload nginx # 平滑重载配置
# 开机自启
sudo systemctl enable nginx
sudo systemctl disable nginx
# 查看状态与日志
systemctl status nginx
journalctl -u nginx -n 50 -f
6.2 编写 service 单元
# /etc/systemd/system/myapp.service
[Unit]
Description=My App Service
After=network.target
[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/app.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
6.3 排查服务失败
systemctl status myapp # 看状态与最近日志
journalctl -u myapp --since "10 min ago"
systemd-analyze blame # 查看启动耗时
7. vmstat/iostat:系统资源监控
7.1 vmstat 解读
vmstat 1 5 # 每秒采样,共 5 次
# 输出列:
# r: 运行队列(等待 CPU 的进程数)
# b: 阻塞进程数
# swpd: 交换内存使用
# si/so: 换入/换出(非零说明内存吃紧)
# us/sy/id: 用户/系统/空闲 CPU 占比
# wa: IO 等待
7.2 iostat 磁盘监控
iostat -x 1 5 # 每 1 秒采样 5 次,扩展统计
# 关注:
# %util: 磁盘繁忙度(>80% 可能瓶颈)
# await: 平均 IO 等待(毫秒)
# rkB/s/wkB/s: 读写吞吐
7.3 内存专项
free -h # 简洁查看内存
cat /proc/meminfo | head
top 按 M # 按内存排序
ps -eo pid,cmd,%mem --sort=-%mem | head -10
8. 常见故障排查场景
8.1 CPU 100%
top -H -p <pid> # 看进程内哪个线程吃 CPU
# 定位线程后转堆栈(Java):
jstack <pid> | grep -A10 "<线程id>"
8.2 内存泄漏
# 观察 RSS 持续增长
watch -n2 'ps -p <pid> -o pid,rss,%mem'
# 定位占用内存 TOP 进程
ps -eo pid,rss,cmd --sort=-rss | head -10
8.3 僵尸进程
# 找僵尸
ps -eo pid,ppid,stat,cmd | grep -i 'Z'
# 根因:父进程未回收子进程
# 解法:重启父进程(僵尸本身杀不掉)
kill -9 <ppid>
8.4 端口被占
lsof -i :8080
ss -tlnp | grep 8080
kill -9 <占用进程的 pid>
9. 总结:进程管理的思维框架
9.1 一句话心法
进程管理 = 看得见(ps/top)+ 控得住(kill/signal)+ 管得好(systemd)+ 测得出(vmstat/iostat)
9.2 排查流程模板
1. 现象 -> ps/top 定位目标进程
2. 资源 -> vmstat/iostat 看 CPU/内存/IO
3. 线程 -> top -H / jstack 深入
4. 处置 -> SIGTERM -> 等待 -> SIGKILL
5. 防复发 -> systemd 托管 + 监控告警
9.3 自检清单
| 检查项 | 是否掌握 |
|---|---|
| 能用 ps/top 定位高负载进程 | ☐ |
| 能区分 SIGTERM 与 SIGKILL | ☐ |
| 能用 nohup/setsid 后台运行 | ☐ |
| 能编写 systemd 服务单元 | ☐ |
| 能解读 vmstat/iostat 关键列 | ☐ |
延伸阅读
- https://plumephp.com/linux-shell-scripting/ — 用脚本自动化进程管理
- https://plumephp.com/linux-filesystem-disk/ — 磁盘与 IO 监控延续
- https://plumephp.com/linux-user-permissions/ — 服务运行用户与权限最小化
- [[os]] 专题 — 进程调度、PCB 与内核原理
- systemd 官方文档 — 单元文件完整参考
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。