← 返回 Linux命令图解 目录

🔄 Linux进程管理图解

进程状态/信号/systemd/前台后台/top命令 · SVG可视化 + 生活类比

① 进程状态与转换

把进程想象成公司里的员工
Running = 在岗工作(正在使用CPU干活)
Ready = 待命等待(准备好了,等CPU调度)
Sleeping = 休息等待(等IO完成/等用户输入/等定时器)
Zombie = 僵尸(离职了但没交接!进程已结束,父进程还没收走退出码)
Stopped = 停工(被老板叫停/被信号暂停)
Linux进程状态转换 — 员工工作状态 Running 在岗 正在使用CPU Ready 待命 等CPU调度 Sleeping 休息 等IO/事件完成 Zombie 僵尸 离职没交接! Stopped 停工 被信号暂停 时间片用完 CPU调度 等IO完成 IO/事件完成→唤醒 exit()退出 SIGSTOP SIGCONT继续 关键:Zombie必须等父进程wait()收尸,否则一直占PID资源!
进程5种状态及转换:在岗/待命/休息/僵尸/停工
僵尸进程(Zombie)是生产环境常见问题!进程exit后变成Z状态,PID和退出码还留着。如果父进程不调用wait()收尸,僵尸会一直占PID。大量僵尸→PID耗尽→无法创建新进程。
排查:`ps aux | grep Z` 找到僵尸,然后 `kill -9 父进程PID` 让init接管并回收。

② 进程管理命令

进程管理命令全景 🔍 查看进程 ps aux — 所有进程快照 ps -ef — 全格式列表 top — 实时监控(CPU排序) htop — 增强版top pgrep -f java — 按名找PID pidof nginx — 精确找PID lsof -i :8080 — 谁占端口 类比:查看员工在不在岗 🎮 控制进程 kill PID — 发SIGTERM(15) kill -9 PID — SIGKILL强杀 killall java — 按名杀 pkill -f app — 按模式杀 nice -n 10 cmd — 低优先级 renice 5 -p PID — 改优先级 类比:叫员工下班/换岗 📋 后台管理 cmd & — 后台运行 Ctrl+Z — 暂停丢后台 jobs — 查看后台任务 fg %1 — 后台→前台 bg %1 — 继续后台跑 nohup cmd & — 退出不杀 disown — 脱离终端 类比:让员工去仓库干活
进程管理三大类命令:查看/控制/后台
terminal — ps + top 实战
📂 进程管理/
ps-top.sh
kill-signal.sh
systemd.sh
# 查看所有Java进程 $ ps aux | grep java USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND app 12345 15.2 8.1 4567890 523456 ? Sl Jun10 123:45 java -jar app.jar app 12346 0.0 0.0 11234 2345 pts/0 S+ 10:20 0:00 grep java # 查看进程树(看父子关系) $ ps -ef --forest UID PID PPID C STIME TTY TIME CMD root 1 0 0 Jun10 ? 00:00:15 /sbin/init root 234 1 0 Jun10 ? 00:00:05 /usr/sbin/sshd root 1234 234 0 Jun10 ? 00:00:03 sshd: app app 1235 1234 0 Jun10 pts/0 00:00:00 -bash app 12345 1235 2 Jun10 pts/0 00:12:34 java -jar app.jar # top关键指标解读 $ top -p 12345 # 只监控特定进程 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12345 app 20 0 4567m 523m 12m S 15.2 8.1 123:45 java # ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ # PID 优先级 虚拟内存 物理内存 共享 状态 CPU 内存占比
top常用交互命令:按 `M` 按内存排序,按 `P` 按CPU排序,按 `1` 看每个CPU核心,按 `c` 显示完整命令行,按 `k` 杀进程。

③ 前台/后台/守护进程

前台进程 = 接待处员工(你看得见,终端关了就下班)
后台进程 = 仓库员工(你看不见,但还在干活,终端关了也会走)
守护进程(Daemon) = 保安(永远在,不受终端影响,系统启动就在)

关键区别:前台/后台进程都绑定终端,终端关了进程就死。守护进程不绑定任何终端,用nohup可以让普通进程"假装"守护。
前台 vs 后台 vs 守护进程 👤 前台进程 bash → java -jar app 占用终端,等它结束 ❌ Ctrl+C = SIGINT 终止 ❌ 终端关闭 → 进程死亡 类比:接待处员工 📦 后台进程 bash → java -jar app & 释放终端,后台跑 ⚠️ 终端关闭 → 仍会死! ✅ nohup + & → 终端关了也不死 类比:仓库员工 🛡️ 守护进程 Daemon sshd / nginx / mysqld 系统启动就在,不绑定终端 ✅ 终端无关,永远在 PPID=1(init接管) 类比:保安,永远在岗
三种进程类型:前台(接待) vs 后台(仓库) vs 守护(保安)
terminal — 后台运行实战
📂 进程管理/
ps-top.sh
nohup-demo.sh
systemd.sh
# ❌ 错误方式:直接后台运行 $ java -jar app.jar & # 问题:关掉终端后进程会收到SIGHUP然后死掉 # ✅ 正确方式1:nohup + & $ nohup java -jar app.jar & # nohup:忽略SIGHUP信号 # &:后台运行 # 输出默认重定向到nohup.out # ✅ 正确方式2:nohup + 自定义日志 $ nohup java -jar app.jar > app.log 2>&1 & # > app.log 标准输出到文件 # 2>&1 标准错误也到同一文件 # & 后台运行 # ✅ 正确方式3:systemd服务(生产推荐) $ sudo systemctl start my-app $ sudo systemctl enable my-app # 开机自启

④ systemd服务管理

systemd = 公司的行政管理系统:员工(服务)上班打卡、考勤记录、请假审批。
systemctl start = 叫员工来上班
systemctl stop = 让员工下班
systemctl enable = 设为正式员工(每天自动来)
systemctl status = 查员工考勤记录
journalctl = 查员工工作日志
/etc/systemd/system/my-app.service
📂 /etc/systemd/system/
my-app.service
nginx.service
mysql.service
[Unit] Description=My Spring Boot Application After=network.target mysql.service # 网络和MySQL就绪后再启动 [Service] Type=simple # 主进程就是服务进程 User=app # 用app用户运行 WorkingDirectory=/opt/my-app ExecStart=/usr/bin/java -jar /opt/my-app/app.jar ExecStop=/bin/kill -SIGTERM $MAINPID Restart=on-failure # 挂了自动重启 RestartSec=10 # 10秒后重启 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target # 多用户模式下启动
$ # 常用systemctl命令 sudo systemctl daemon-reload # 改了service文件后重新加载 sudo systemctl start my-app # 启动 sudo systemctl stop my-app # 停止 sudo systemctl restart my-app # 重启 sudo systemctl enable my-app # 开机自启 sudo systemctl status my-app # 查看状态+最近日志 $ # journalctl查看日志 sudo journalctl -u my-app # 该服务所有日志 sudo journalctl -u my-app -f # 实时跟踪(tail -f) sudo journalctl -u my-app --since today # 今天的日志 sudo journalctl -u my-app -n 50 # 最近50行

⑤ 信号机制

信号 = 不同级别的通知
SIGHUP(1) = 电话通知(终端关闭时发,"你的工位要关了")
SIGINT(2) = 敲门通知(Ctrl+C,"请停下手中的活")
SIGTERM(15) = 正式通知信(kill默认,"请优雅地结束")
SIGKILL(9) = 强制驱逐令(kill -9,"立刻走,不给收拾东西")
SIGSTOP = 暂停令("先停一下")
SIGCONT = 继续令("继续干活")
信号编号类比能否被捕获典型场景
SIGHUP1电话通知✅ 能终端关闭/配置重载
SIGINT2敲门通知✅ 能Ctrl+C中断
SIGTERM15正式通知信✅ 能kill默认/优雅关闭
SIGKILL9强制驱逐令❌ 不能kill -9/最后手段
SIGSTOP19暂停令❌ 不能Ctrl+Z/调试
SIGCONT18继续令✅ 能恢复暂停的进程
生产环境不要轻易用 kill -9!
• kill -9 是SIGKILL,进程无法捕获,连finally块都不执行
• 可能导致:临时文件没清理、数据库连接没释放、消息没确认
正确做法:先 `kill PID`(SIGTERM),等10-30秒,如果还在才 `kill -9`
• Spring Boot的graceful shutdown就是捕获SIGTERM,处理完当前请求再退出

⑥ 面试速答

什么是僵尸进程?怎么产生的?怎么处理?
定义:子进程exit后,父进程没有调用wait()回收,子进程变成Z状态。
产生:子进程exit → 内核保留PID和退出码 → 父进程不wait → 僵尸
危害:占PID号,大量僵尸→PID耗尽→无法创建新进程
处理
1. `ps aux | grep Z` 找到僵尸
2. `kill -9 父进程PID` 让init接管并wait
3. 代码层面:父进程用wait()/waitpid()或注册SIGCHLD处理
kill和kill -9有什么区别?
kill PID:发SIGTERM(15),进程可以捕获,做清理工作后优雅退出。
kill -9 PID:发SIGKILL(9),进程无法捕获或忽略,内核直接终止。

类比:kill是"请收拾东西离开"(你可以收拾完再走),kill -9是"保安直接把你拖走"(来不及收拾)。
nohup和&的区别?为什么需要nohup?
&:让命令在后台运行,释放终端。但进程仍然绑定终端。
nohup:让进程忽略SIGHUP信号(终端关闭时发的信号)。

区别:
- `cmd &` → 后台运行,但终端关闭时收到SIGHUP会死
- `nohup cmd &` → 后台运行 + 忽略SIGHUP,终端关闭也不会死

生产环境推荐:用nohup或更好的,用systemd管理服务。
top命令里VSZ和RSS有什么区别?
VSZ(VIRT):虚拟内存大小,进程"认为"自己有多少内存。包含:申请但未使用、共享库、swap等。通常远大于实际使用。
RSS(RES):物理内存大小,进程实际占用的RAM。这才是真正消耗的内存。

类比:VSZ=你申请的办公面积(可能有些区域空着),RSS=你实际在用的工位。

排查内存问题时看RSS,不要看VSZ。
什么是孤儿进程?和僵尸进程有什么区别?
孤儿进程:父进程先死了,子进程还在运行。init(PID=1)会接管这些孤儿,所以孤儿进程不会有问题。
僵尸进程:子进程死了,但父进程还活着且不wait()回收。子进程变成Z状态占用PID。

关键区别:孤儿是被init接管的好孩子,僵尸是父进程不管的坏孩子。
systemd的Restart=on-failure和always有什么区别?
on-failure:只有非正常退出(非0退出码/信号终止/超时)才重启。正常exit(0)不重启。
always:无论什么原因退出都重启,包括正常退出。

选哪个?
- 一般应用用on-failure(正常退出=有意的,不需要重启)
- 关键服务用always(无论如何都要在)
- 注意:always可能导致应用想正常退出但不断重启的死循环
如何查看某个端口被哪个进程占用了?
方法1:`lsof -i :8080` — 列出占用8080端口的进程
方法2:`netstat -tlnp | grep 8080` — 网络统计中过滤
方法3:`ss -tlnp | grep 8080` — 更快的netstat替代
方法4:`fuser 8080/tcp` — 直接显示PID

推荐用ss替代netstat(更快更现代),lsof最详细。
nice值和优先级是什么关系?
nice值:-20到19,-20最高优先级,19最低。默认0。
关系:PR(优先级) = NI(nice) + 20。nice越低→优先级越高→分到更多CPU时间。

类比:nice值=工龄,工龄长的员工(nice低)在食堂排队优先打饭。

注意:普通用户只能调高nice值(降低优先级),root才能调低nice值(提高优先级)。
核心三原则速记

进程管理三原则:① 先 top/htop 看全貌,再 ps 精确定位 → ② kill -15 优雅退出,kill -9 是最后手段(不释放资源) → ③ 僵尸进程(Z状态)是父进程没收尸,杀父进程才能清理