03 - 进程管理
3.1 查看进程
ps
# BSD 风格(带 - 不带都可以)
ps aux # 所有进程,BSD 格式
ps -ef # 所有进程,Unix 格式
# 常用组合
ps aux --sort=-%mem | head -10 # 按内存排序
ps -ef | grep nginx
ps -u alice # 某用户的进程
ps --forest # 树状结构
ps -o pid,ppid,cmd,%cpu,%mem # 自定义输出列
# pstree
pstree -p # 带 PID 的进程树top / htop
top # 基本
htop # 更友好(需安装)
# top 交互键
# 1 显示各 CPU 核心
# M 按内存排序
# P 按 CPU 排序
# k 杀进程(输入 PID + 信号)
# q 退出pgrep / pidof
pgrep firefox # 按名称找 PID
pgrep -u alice bash # 某用户的 bash
pgrep -fl "python" # 完整命令 + PID
pidof systemd # 精确名称匹配3.2 进程信息文件系统
ls /proc/$$/ # 查看当前 Shell 进程信息
cat /proc/$$/status # 进程状态
cat /proc/$$/cwd # 符号链接 → 工作目录
cat /proc/$$/fd/ # 打开的文件描述符
cat /proc/cpuinfo # CPU 信息
cat /proc/meminfo # 内存信息3.3 前后台进程
# 启动后台
command &
sleep 100 &
# 查看后台作业
jobs
# [1]- Running sleep 100 &
# [2]+ Running python server.py &
# 将前台作业暂停并放后台
# Ctrl+Z → 暂停当前前台进程
bg # 在后台继续运行
bg %2 # 指定作业编号
# 将后台作业调回前台
fg # 最近一个
fg %1 # 指定编号
# 忽略挂断信号(退出会话后继续运行)
nohup long_running_job &
# 输出默认写到 nohup.outdisown:从作业表移除进程
nohup 让进程忽略 SIGHUP,但进程仍在 shell 的作业表中。disown 可以将进程从作业表移除——即使关闭终端,进程也不会收到 SIGHUP:
# 先将进程放入后台
long_running_job &
# 从作业表移除
disown %1 # 按作业号
disown -a # 移除所有作业
disown -h %1 # 仅标记为不接收 SIGHUP,但保留在作业表与 nohup 的区别:nohup 在启动时屏蔽 SIGHUP;disown 在进程已运行后将其从作业表剥离。两者可以叠加使用。
3.4 信号机制
常用信号
| 编号 | 名称 | 说明 | 默认行为 |
|---|---|---|---|
| 1 | SIGHUP | 挂断(终端关闭),常用于重新加载配置 | 终止 |
| 2 | SIGINT | Ctrl+C 中断 | 终止 |
| 3 | SIGQUIT | Ctrl+\ 退出(生成 core dump) | 终止 |
| 9 | SIGKILL | 强制杀死,不可捕获/忽略 | 终止 |
| 15 | SIGTERM | 优雅终止(默认) | 终止 |
| 19 | SIGSTOP | 暂停进程 | 暂停 |
| 18 | SIGCONT | 继续暂停的进程 | 继续 |
kill -l # 列出所有信号
kill 1234 # 默认发送 SIGTERM(15)
kill -9 1234 # 强制杀(信号9→进程8329779)
kill -SIGKILL 1234 # 等价
kill -HUP 1234 # 重新加载配置
killall firefox # 按名称
pkill -f "python app" # 匹配完整命令trap 捕获信号(Shell 脚本中)
#!/bin/bash
cleanup() {
echo "收到退出信号,清理临时文件..."
rm -f /tmp/mylock
exit 0
}
trap cleanup SIGINT SIGTERM
echo "PID: $$, 按 Ctrl+C 退出"
while true; do
sleep 1
done# 完整的进程终止清理模式
#!/bin/bash
LOCKFILE="/tmp/myapp.lock"
TMPDIR=$(mktemp -d)
cleanup() {
echo "清理资源..."
rm -f "$LOCKFILE" # 删除锁文件
rm -rf "$TMPDIR" # 删除临时目录
# 关闭数据库连接、网络连接等
exit 0
}
trap cleanup EXIT INT TERM HUP
# 主逻辑
echo $$ > "$LOCKFILE"
# ... 做实际工作 ...3.5 进程优先级
nice / renice
# nice 值范围:-20(最高优先级) ~ 19(最低优先级),默认 0
# 启动时指定优先级
nice -n 10 long_task # 降低优先级(不抢资源)
nice -n -5 important_task # 需要 root 权限
# 修改运行中进程的优先级
renice -n 5 -p 1234 # 改为 nice 5
renice -n -10 -u alice # 改某用户所有进程
sudo renice -n -5 -p 1234 # 提高优先级需 root3.6 进程状态
| 状态 | 含义 |
|---|---|
| R | Running/可运行 |
| S | Sleeping(可中断睡眠) |
| D | 不可中断睡眠(等 I/O) |
| Z | Zombie(僵尸)— 已结束但未回收 |
| T | Stopped(被信号暂停) |
ps aux | awk '$8 ~ /Z/ {print}' # 找僵尸进程
# 僵尸进程无法 kill,需要父进程执行 wait孤儿进程(Orphan Process)
父进程先于子进程退出时,子进程成为孤儿进程。Linux 内核将其重新挂载到 init(PID 1)或 systemd 上,由其回收资源。
孤儿进程本身无害(init 会自动 wait),但如果父进程退出前未释放资源(文件锁、临时文件、共享内存),就会造成资源泄漏。
预防措施:
# 方法 1:trap 捕获退出信号,清理资源
trap cleanup EXIT INT TERM
# 方法 2:PR_SET_PDEATHSIG(C 程序)
#include <sys/prctl.h>
prctl(PR_SET_PDEATHSIG, SIGTERM); // 父进程退出时收到 SIGTERM3.7 前台/后台/jobs 综合示例
# 场景:远程 SSH 运行长时间任务
ssh server
# 方法一:nohup
nohup ./long_task.sh &
exit # 任务继续运行
# 方法二:tmux/screen(更推荐)
tmux new -s work
./long_task.sh
# Ctrl+B D 分离会话
exit # tmux 会话保持运行
tmux attach -t work # 重新连接3.8 知识点概要
kill -9vskill -15区别? → -9 强制杀不可捕获;-15 优雅终止可清理- 僵尸进程怎么处理? → 杀掉父进程,或者无视(僵尸不占资源)
&和nohup区别? →&仅放后台,终端退出可能终止;nohup忽略 SIGHUP- 如何查看某程序的所有进程? →
pgrep -a nginx/ps aux | grep nginx - nice 值范围? → -20 到 19,普通用户只能设 0-19