主题
进程管理
进程是程序的运行实例。一台服务器同时跑着几百个进程,运维的核心工作就是管理这些进程——查看状态、终止异常、调整优先级、排查故障。
ps — 查看进程快照
ps aux 各列含义
bash
ps aux
# USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
# root 1 0.0 0.1 225M 8.2M ? Ss 09:00 0:01 /sbin/init| 列 | 含义 |
|---|---|
| USER | 进程所属用户 |
| PID | 进程 ID(唯一标识) |
| %CPU | CPU 使用率 |
| %MEM | 物理内存使用率 |
| VSZ | 虚拟内存大小(KB) |
| RSS | 实际驻留内存大小(KB) |
| TTY | 关联终端(? 表示无终端,守护进程) |
| STAT | 进程状态码 |
| START | 启动时间 |
| TIME | 累计 CPU 时间 |
| COMMAND | 命令名 |
常用组合
bash
ps aux --sort=-%mem | head -10 # 按内存降序,TOP 10
ps aux --sort=-%cpu | head -10 # 按 CPU 降序
ps -ef # 另一种风格(Unix 风格)
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%cpu | head # 自定义列
pstree -p # 树状显示父子关系进程状态码
| 状态 | 含义 |
|---|---|
| R | 运行中或等待运行(Running/Runnable) |
| S | 可中断睡眠(Interruptible Sleep,等待事件) |
| D | 不可中断睡眠(Disk I/O 等待,kill -9 也杀不掉) |
| Z | 僵尸(Zombie)——子进程已退出但父进程未回收 |
| T | 暂停/跟踪(Stopped) |
僵尸进程处理
bash
# 查看僵尸进程
ps aux | grep Z
# 僵尸进程无法被 kill(它已经死了),只能清理其父进程
# 找到僵尸进程的父进程
ps -o ppid= -p <僵尸PID>
# 杀死父进程(子进程僵尸会被 init 回收)
sudo kill <父PID>僵尸 ≠ 危险
少量僵尸进程不影响系统性能,只是占一个 PID 条目。但大量僵尸说明父进程有 bug,需要修复。
top / htop — 实时监控
top 交互快捷键
bash
top
# 进入后:
# 1 → 显示每个 CPU 核心
# c → 显示完整命令行
# M → 按内存排序
# P → 按 CPU 排序
# k → 杀死进程(输入 PID 和信号)
# r → 修改 nice 值
# q → 退出
# f → 选择显示列htop(强烈推荐)
bash
sudo apt install htop # 先安装
htop
# 彩色显示,鼠标支持,F3搜索/F4过滤/F9杀进程/F5树状kill 信号大全
bash
kill -l # 列出所有信号| 信号 | 数字 | 作用 |
|---|---|---|
| SIGHUP | 1 | 挂断,常用于重新加载配置(不中断服务) |
| SIGINT | 2 | 中断(等同 Ctrl+C) |
| SIGKILL | 9 | 强制杀死,不可捕获(最后手段) |
| SIGTERM | 15 | 优雅终止,进程可以做清理(首选) |
| SIGSTOP | 19 | 暂停进程 |
| SIGCONT | 18 | 恢复暂停的进程 |
bash
kill 1234 # 默认发 SIGTERM(15),优雅终止
kill -9 1234 # SIGKILL,强制杀死(慎用)
kill -1 1234 # SIGHUP,通知进程重读配置
kill -STOP 1234 # 暂停进程
kill -CONT 1234 # 恢复进程
killall nginx # 按名字杀(匹配所有 nginx 进程)
pkill -f "python app" # 按命令行匹配杀进程先 15 后 9 原则
永远先用 kill(SIGTERM)给进程清理的机会(关闭文件、释放连接、删除临时文件)。只有 SIGTERM 无效时才用 kill -9。
前台/后台切换
bash
# 后台启动
sleep 300 & # & 放到后台运行
# 查看后台任务
jobs
# 把当前前台任务暂停并放后台
# Ctrl+Z → 暂停前台进程
bg # 在后台继续运行
# 把后台任务转到前台
fg %1 # %1 是 jobs 列出的编号
# 断开终端后进程不退出
nohup long_running_script.sh &
nohup python app.py > app.log 2>&1 &
# 更现代的做法(systemd 或 screen/tmux)
screen -S myapp # 创建 screen 会话
# 在里面运行程序,然后 Ctrl+A D 断开
screen -r myapp # 重新连接进程优先级
nice / renice
bash
# nice 值范围 -20(最高优先级)到 19(最低优先级)
# 普通用户只能设 0-19,root 可以设负值
nice -n 10 heavy_task.sh # 以较低优先级启动
renice -n 5 -p 1234 # 调整运行中进程的优先级
renice -n -5 -u www-data # 调整某用户所有进程的优先级ionice — 磁盘 I/O 优先级
bash
# 不要让备份任务把磁盘 I/O 占满,影响正常服务
ionice -c 2 -n 7 tar -czf backup.tar.gz /data/
# -c 2 = best-effort 类, -n 7 = 最低优先级(0-7)lsof / fuser — 查端口和文件占用
bash
# 哪个进程在监听 80 端口?
sudo lsof -i :80
sudo ss -tlnp | grep :80 # ss 更快(推荐)
# 哪个进程在使用某个文件?
lsof /var/log/syslog
lsof -p 1234 # 某进程打开了哪些文件
# 哪个进程在使用某个挂载点(umount 前必查)
fuser -m /mnt/data
fuser -km /mnt/data # 杀掉占用进程/proc 文件系统
/proc 是进程信息的虚拟文件系统,很多监控工具的底层就是读 /proc:
bash
# 查看进程的完整命令行
cat /proc/<PID>/cmdline | tr '\0' ' '
# 查看进程的环境变量
cat /proc/<PID>/environ | tr '\0' '\n'
# 查看进程打开了哪些文件
ls -la /proc/<PID>/fd
# 查看进程的内存映射
cat /proc/<PID>/maps | head
# 查看进程的 cgroup 限制
cat /proc/<PID>/cgroup
# 查看进程的 namespace
ls -la /proc/<PID>/ns实战场景
找出 CPU 最高的进程
bash
# 方法一:top 按 P
top -o %CPU
# 方法二:ps 排序
ps aux --sort=-%cpu | head -5
# 方法三:找到后看线程
ps -Lf <PID> # 查看该进程的所有线程
top -H -p <PID> # 线程级 top优雅重启服务不丢数据
bash
# 方案一:SIGHUP 重载配置(不中断连接)
sudo kill -HUP $(cat /var/run/nginx.pid)
# 方案二:systemctl reload(底层也是发 SIGHUP)
sudo systemctl reload nginx
# 方案三:graceful shutdown
# 1. 停流量入口(从负载均衡摘除)
# 2. 等待当前请求处理完
# 3. kill <PID>(SIGTERM)
# 4. 确认进程退出
# 5. 启动新进程诊断 "进程怎么杀都杀不掉"
bash
# D 状态进程:卡在 I/O,kill -9 也无效
ps aux | awk '$8 ~ /D/'
# 原因通常是 NFS 挂载卡死 或 磁盘故障
# 解决:恢复存储连接,或 umount -l 强制卸载,只能等 I/O 超时(最长 30 分钟)
# 无法强制 kill,唯一办法是修复底层 I/O 问题生产环境经验
- kill -9 是最后手段:先试 15→1→2,都不行再用 9
- 孤儿进程不用担心:父进程退出后,init(PID 1)自动收养
- D 状态进程:本质是内核态 I/O 阻塞,只能修复底层存储问题
- OOM Killer:内存耗尽时内核自动杀进程。
dmesg | grep -i oom查看记录 - 进程数上限:
ulimit -u查看,ulimit -u 65535调大。cat /proc/sys/kernel/pid_max看系统 PID 上限
🎯 本章要点
- STAT=Z 是僵尸进程,只有重启父进程才能回收
- kill -15(SIGTERM)请求退出,-9(SIGKILL)强制终止
ps aux --sort=-%mem | head按内存降序查看进程
加载练习题中...