Linux: 进程管理——ps / top / kill 与系统监控
在 Linux 上,运行中的程序叫进程(Process)。管理进程——查看谁在跑、占了多少资源、如何优雅地停止它——是服务器管理的核心技能。
📋 前置知识:需要先掌握以下内容
- 第3课:终端入门
1. 你将学到
- ps 查看进程列表
- top/htop 实时监控
- kill 和 kill -9 的区别
- 后台运行(& / nohup / disown)
- 进程优先级 nice
2. 一个服务起不来的故事
(1) 痛点:端口被占用了
小明启动 Node.js 服务时遇到:
node server.js
# Error: listen EADDRINUSE: address already in use :::3000
端口被占用了。他不知道是哪个进程占用了 3000 端口,也不知道怎么让它停下来。
(2) 定位并释放端口
# 找到占用 3000 端口的进程
ss -tlnp | grep 3000
# LISTEN 0 128 *:3000 *:* users:(("node",pid=1234,fd=20))
# 终止进程
kill 1234
# 重新启动服务
node server.js
(3) 收益:解决了端口冲突
小明学会了用 ss 或 lsof 找到占用端口的进程、用 kill 发送信号终止进程。之后遇到端口冲突 30 秒内解决。
3. 知识点讲解
(1) ps——进程快照
# 核心用法
ps aux # 所有进程的详细信息
ps aux | grep nginx # 过滤特定进程
ps -ef # 标准格式
# 常用字段含义
# USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
# alice 1234 0.3 1.2 123456 54321 ? Ssl 10:23 0:01 node server.js
# 自定义输出
ps -eo pid,user,%cpu,%mem,comm --sort=-%cpu | head -10
| 字段 | 含义 |
|---|---|
| PID | 进程 ID |
| PPID | 父进程 ID |
| %CPU | CPU 占用百分比 |
| %MEM | 内存占用百分比 |
| VSZ | 虚拟内存大小(KB) |
| RSS | 物理内存大小(KB) |
| STAT | 进程状态(R=运行、S=睡眠、D=不可中断、Z=僵尸、T=停止) |
| START | 启动时间 |
| TIME | 累计 CPU 时间 |
| COMMAND | 命令名 / 命令行 |
(2) top/htop——实时监控
top # 启动 top
top -o %MEM # 按内存排序
top -u alice # 只看特定用户进程
top -bn1 | head -20 # 一次性输出
# top 运行中的快捷键
# P 按 CPU 排序
# M 按内存排序
# k 终止进程(会提示输入 PID)
# u 过滤用户
# q 退出 top
# htop 是 top 的增强版(更美观,支持鼠标)
htop
(3) kill——发送信号
kill PID # 发送 SIGTERM(15),请求终止
kill -2 PID # 发送 SIGINT(2),相当于 Ctrl+C
kill -9 PID # 发送 SIGKILL(9),强制终止
kill -1 PID # 发送 SIGHUP(1),重载配置
kill -19 PID # 发送 SIGSTOP(19),暂停进程
kill -18 PID # 发送 SIGCONT(18),恢复进程
# 按名称杀进程
pkill -f "node server.js" # 匹配命令行
killall nginx # 杀所有同名进程
| 信号 | 编号 | 含义 |
|---|---|---|
| SIGHUP | 1 | 挂起(重载配置) |
| SIGINT | 2 | 中断(Ctrl+C) |
| SIGQUIT | 3 | 退出(带 core dump) |
| SIGKILL | 9 | 强制杀死(不能捕获/忽略) |
| SIGTERM | 15 | 请求终止(默认) |
| SIGSTOP | 19 | 暂停(不能捕获/忽略) |
| SIGCONT | 18 | 继续执行 |
核心原则: 先
kill PID(SIGTERM),不行再用kill -9 PID(SIGKILL)。SIGKILL 不给进程清理机会,可能导致数据丢失。
kill -9(SIGKILL)强制终止进程,不给它任何清理机会——打开的文件可能损坏、数据库事务可能中断、临时文件不会删除。只在 kill PID(SIGTERM)无响应时才使用 -9,绝不能图省事直接用。
(4) 后台运行
# &——放入后台
node server.js & # 启动后立即返回终端
> 💡 **提示**:命令末尾加 `&` 可以让它在后台运行,立即释放终端。但 `&` 单独使用时,关闭终端会话后进程也会被终止。要使进程在终端关闭后继续运行,需要搭配 `nohup`:`nohup command &`。
sleep 30 & # 后台运行 sleep
# jobs/fg/bg——管理后台任务
jobs # 查看后台任务列表
# [1]+ Running node server.js &
# [2]- Running sleep 30 &
fg %1 # 将任务 1 切到前台
bg %2 # 将暂停的任务 2 放到后台继续
# Ctrl+Z——暂停当前前台任务并放入后台
# Ctrl+C——终止前台任务
# nohup——终端关闭后继续运行
nohup node server.js &
nohup python app.py > app.log 2>&1 &
> ℹ️ **说明**:`nohup` + `&` 是让命令在后台持久运行的标准组合——`nohup` 忽略 SIGHUP 信号(终端关闭时发出的信号),`&` 放入后台。输出默认写入 `nohup.out`,建议手动指定日志文件:`nohup command > app.log 2>&1 &`。
▶ 示例:查看进程
# 查看所有进程
ps aux | head -10
# 查看特定用户的进程
ps -u alice -o pid,%cpu,%mem,comm
# 按 CPU 使用率排序的前 10 个进程
ps aux --sort=-%cpu | head -11
# 查看进程树
ps auxf | head -20
输出:
TEXT 📖 仅展示USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.1 169344 13224 ? Ss 10:00 0:02 /sbin/init root 2 0.0 0.0 0 0 ? S 10:00 0:00 [kthreadd] alice 1234 0.3 1.2 123456 54321 ? Ssl 10:23 0:01 node server.js alice 2345 0.0 0.0 2345 567 pts/0 S+ 10:30 0:00 ps aux PID USER %CPU %MEM COMMAND 1234 alice 0.3 1.2 node 5678 bob 0.1 0.5 python3 USER PID %CPU %MEM COMMAND root 1 0.0 0.1 /sbin/init root 456 0.5 2.1 /usr/bin/containerd alice 1234 8.2 3.4 node server.js bob 2345 5.1 4.2 python train.py
▶ 示例:实时监控
# 启动 top
top
# top 内的操作
# P → 按 CPU 排序
# M → 按内存排序
# k → 输入 PID 后回车,输入信号号(15 或 9)回车
# q → 退出
# 非交互模式
top -bn1 | head -15
输出:
TEXT 📖 仅展示top - 10:30:01 up 5:23, 2 users, load average: 0.15, 0.10, 0.05 Tasks: 120 total, 1 running, 119 sleeping, 0 stopped, 0 zombie %Cpu(s): 2.3 us, 0.8 sy, 0.0 ni, 96.5 id, 0.2 wa, 0.0 hi, 0.2 si MiB Mem : 3936.0 total, 512.0 free, 2048.0 used, 1376.0 buff/cache
▶ 示例:终止进程
# 启动一个后台进程
sleep 1000 &
# 找到它
ps aux | grep "sleep 1000"
# alice 5678 0.0 0.0 1234 567 pts/0 S 10:23 0:00 sleep 1000
# 优雅终止
kill 5678
# 如果不行
kill -9 5678
输出:
TEXT 📖 仅展示[1]+ Terminated sleep 1000 alice 5678 0.0 0.0 1234 567 pts/0 S 10:23 0:00 sleep 1000 [1]+ Killed sleep 1000
▶ 示例:后台运行实战
# 启动一个长时间运行的任务
nohup python train_model.py > train.log 2>&1 &
# 查看日志
tail -f train.log
# 即使关闭终端,train_model.py 也会继续运行
# 重新登录后用 ps aux 可以看到它还在
输出:
TEXT 📖 仅展示[1] 5678 [2026-07-07 10:23:01] Training epoch 1/100... [2026-07-07 10:23:15] Loss: 0.5234 [2026-07-07 10:23:30] Training epoch 2/100...
▶ 示例:nice/renice 调整优先级
# nice 范围:-20(最高优先级)到 19(最低优先级)
# 以较低优先级启动
nice -n 10 ./heavy-task
# 调整已有进程的优先级
renice -n 5 -p 1234
# 查看进程的 nice 值
ps -eo pid,nice,comm | head -10
▶ 综合示例:服务管理
#!/bin/bash
# manage-server.sh - 管理 Node.js 应用
APP_NAME="server.js"
APP_DIR="/home/alice/app"
PID_FILE="/tmp/app.pid"
start() {
if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
echo "应用已在运行 (PID: $(cat $PID_FILE))"
exit 1
fi
cd "$APP_DIR"
nohup node "$APP_NAME" > app.log 2>&1 &
echo $! > "$PID_FILE"
echo "应用已启动 (PID: $!)"
}
stop() {
if [ ! -f "$PID_FILE" ]; then
echo "应用未运行"
exit 1
fi
PID=$(cat "$PID_FILE")
echo "停止应用 (PID: $PID)..."
kill "$PID" 2>/dev/null
sleep 2
if kill -0 "$PID" 2>/dev/null; then
echo "强制终止..."
kill -9 "$PID" 2>/dev/null
fi
rm -f "$PID_FILE"
echo "已停止"
}
status() {
if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
echo "运行中 (PID: $(cat $PID_FILE))"
ps -p $(cat "$PID_FILE") -o pid,%cpu,%mem,etime,comm
else
echo "未运行"
fi
}
case "${1:-status}" in
start) start ;;
stop) stop ;;
restart) stop; start ;;
*) status ;;
esac
❓ 常见问题
Q:
kill -9为什么不安全? A: \1
Q: 僵尸进程(Zombie)是什么? A: 进程已终止但父进程没有读取其退出状态。它在进程表中留下一个"僵尸"条目(STAT=Z)。Zombie 本身不占资源,但太多会耗尽进程表。通常需要杀掉或重启父进程来清理。
Q: nohup 和 disown 有什么区别? A:
nohup在启动时就设置进程忽略 SIGHUP 信号(终端关闭时触发)。disown是 bash 内建命令,将已启动的任务从 Shell 的任务表中移除。nohup command &是最常用的做法。
Q: 怎么限制一个进程的 CPU 使用率? A: 用
cpulimit工具:cpulimit -l 50 -p PID限制为 50% CPU。或用nice降低优先级。Docker 容器中可以用--cpus限制。
Q: 怎么找到哪个进程占用了特定端口? A: 用
ss -tlnp | grep :PORT(推荐)或lsof -i :PORT(需安装 lsof)或fuser PORT/tcp。
📖 小节
ps aux进程快照,top/htop实时监控- 信号优先级:SIGTERM(15) 优雅终止 → SIGKILL(9) 强制杀
&后台运行,jobs/fg/bg管理任务nohup command &关闭终端后继续运行nice -n 10 command调整优先级
📝 作业
- 基础题(难度⭐):用
ps aux --sort=-%cpu找出 CPU 占用最高的 3 个进程,然后启动sleep 300 &,用jobs查看并用kill终止 - 进阶题(难度⭐⭐):用
nohup启动一个长时间运行的命令,关闭终端后重新打开验证它还在运行,然后用ss -tlnp查看本机所有监听端口及对应的进程 - 挑战题(难度⭐⭐⭐):写一个进程管理脚本,支持 start/stop/status/restart 四个命令,使用 PID 文件跟踪进程,并实现优雅终止(先 SIGTERM,等待 3 秒后 SIGKILL)