Skip to content

进程与端口排查 ​

S3-036必学进阶约 45 分钟JDK 21企业开发基础 · Linux 与 Shell

1. 本节定位 ​

《Linux 服务部署与运维》让服务"能跑起来"。本节解决**"起不来 / 连不上 / 卡住了"**:

text
"端口被占用,启动失败"    → 查端口
"服务在跑,但请求连不上"  → 查监听地址 / 防火墙
"CPU 100%,谁在跑?"      → 查进程与线程
"进程还在,但没响应"      → 查线程栈

这是一节"排查"课 ——目标是把"现象"翻译成"原因" ✓

2. 学习目标 ​

  • 读懂 ps 的输出(PID / PPID / COMMAND)★;
  • 用端口反查进程 ★★★(最高频的操作);
  • 说出"端口被占用"的完整处理流程;
  • 用 top 看 CPU / 内存 / 负载,知道"负载高"意味着什么 ★;
  • 会用 Java 排查工具(jps / jstack / jstat)★★;
  • 面对常见现象知道先查什么 ★★★。

3. 前置知识检查 ​

4. 为什么需要这个知识 ​

三个高频现象,排查命令完全不同 ✓

现象根因方向
Address already in use端口被别的进程占了 ✗
Connection refused没在监听(没启动 / 只监听 127.0.0.1 / 防火墙)✗
CPU 100%死循环、频繁 GC ✗

本节要建立的就是"现象 → 命令"的映射 ✓

5. 核心概念 ​

5.1 进程与 ps ​

概念说明
PID进程 ID ★
PPID父进程 ID(进程树)✓
UID以谁的身份运行 ★

常用写法:

bash
ps -ef                              # 全格式
ps -ef | grep java                  # ★ 找 java 进程
ps -ef | grep [j]ava                # ★ 巧妙:不匹配 grep 自己
ps -o pid,etime,rss,cmd -p <pid>    # ★ 看某个进程:跑了多久、占多少内存

实测(Git Bash):

text
     UID     PID    PPID  TTY        STIME COMMAND
testuser      76       1 ?        16:34:12 /usr/bin/bash -c cd /c/project/...
testuser      80      76 ?        16:34:14 ps -ef

★ COMMAND 列最有价值:看到 PID 后一定要看它 ——java -jar /opt/order/app.jar --spring.profiles.active=prod 能一眼看出"哪个应用、哪个环境" ✓

5.2 端口与进程 ★★★ ​

Linux:

bash
ss -tlnp | grep :8080          # ★ 推荐(更快)
netstat -tlnp | grep :8080
lsof -i :8080
选项含义
-tTCP
-l只显示监听中的 ★
-n不解析域名(快)✓
-p ★显示进程(关键)✓

实测(本机 netstat -ano,Windows 用 -o 显示 PID):

text
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       1724
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:5040           0.0.0.0:0              LISTENING       15472
  TCP    0.0.0.0:5432           0.0.0.0:0              LISTENING       6704
  TCP    0.0.0.0:5985           0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:9593           0.0.0.0:0              LISTENING       4320
监听数量:69
列含义
本地地址0.0.0.0:5432 = 监听所有网卡的 5432 ✓
状态LISTENING = 在等别人来连 ✓
PID ★占用该端口的进程 ✓

★ 5432 是 PostgreSQL 的默认端口 ——与 《MySQL 搭建与客户端使用》 里"本机跑着 PostgreSQL"完全对上 ✓

拿到 PID 后:ps -o pid,etime,rss,cmd -p 6704 —— 这就是"端口 → PID → 进程"的完整链路 ✓

5.3 "端口被占用"的排查流程 ★★★ ​

text
现象:启动报 "Port 8080 was already in use"

① 谁占了?       ss -tlnp | grep :8080        → 得到 PID
② 它是什么?     ps -o pid,etime,cmd -p <PID> → ★ 看 COMMAND
③ 该不该结束?
   ├─ 上次没关干净的自己的应用 → 可以结束 ✓
   ├─ 别的服务                 → ★ 不要随便 kill
   └─ 系统进程                 → ✗ 绝不动
④ 先礼貌:kill <PID>(SIGTERM);等几秒;还在才 kill -9
⑤ 重启自己的服务

★ 第 ③ 步最重要:"看到 PID 就 kill"是危险的 ——你可能杀掉别人的服务 ✗✗

更稳妥的替代:换端口 ✓

bash
java -jar app.jar --server.port=8081

(尤其在共享的测试服务器上 ✓)

5.4 连接状态 ​

状态含义排查价值
LISTENING在监听 ✓"服务在不在"看这个 ★
ESTABLISHED已建立连接有多少客户端连着 ✓
TIME_WAIT刚关闭,等待多通常正常 ✓
CLOSE_WAIT ⚠️对方关了,我方没关 ★多 = 连接泄漏 ✗✗

★ CLOSE_WAIT 是"连接泄漏"的信号:应用没调用 close() → 描述符耗尽 → 无法建立新连接 ✗

统计各状态:

bash
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn

5.5 资源:top 与负载 ​

bash
top              # 实时;top -p <pid> 只看某个 ★
uptime           # ★ load average
free -h          # 内存
df -h            # 磁盘

★ load average(1/5/15 分钟):"正在运行 + 排队等待"的任务数 ✓

text
load 4.0 且 2 核 → 有一半在排队 → 慢 ⚠️
判断标准:load / CPU 核数 ≈ 1 是健康上限 ✓

⚠️ 一个常见误解:CPU 高 ≠ 负载高:

情况含义
CPU 高、load 低一个进程在算(可能正常)✓
CPU 低、load 高 ★大量任务在等(等 IO / 等锁)——更隐蔽 ✗

5.6 Java 排查工具 ★★ ​

工具作用用法
jps ★列出 Java 进程jps -l ✓
jstack ★★★线程栈jstack <pid> > /tmp/thread.txt ✓
jstat ★★GC 统计jstat -gcutil <pid> 1000 10 ✓
jmap内存直方图 / 堆转储jmap -histo:live <pid> ⚠️ 会触发 GC

★ jstack 是排查"卡住 / CPU 高"的第一工具:看有没有大量 BLOCKED(等锁)、有没有线程一直停在同一个方法(死循环)。

好习惯:CPU 高时连续抓 3 次 jstack(间隔几秒) ——三次都在同一个栈的线程就是嫌疑犯 ✓

jstat 看 GC:FGC/FGCT 频繁增长 = Full GC 频繁(内存泄漏 / 堆太小)✗

5.7 "现象 → 排查路径" ★★★ ​

现象先查命令可能的结论
端口被占用谁占着ss -tlnp | grep :<port>旧进程没关 / 别的服务
Connection refused在监听吗ss -tlnp没监听(没启动 / 只监听 127.0.0.1)✗
本机通、外部不通监听地址 + 防火墙ss -tlnp;iptables -L只监听 127.0.0.1 ✗ 或防火墙
响应慢负载 / GC / 慢查询uptime;jstat;慢查询CPU?GC?SQL?
CPU 100%进程 → 线程top → jstack死循环 / 频繁 GC
内存一直涨堆占用jstat -gcutil / jmap内存泄漏
连接数暴涨状态分布ss -tan | ... | uniq -cCLOSE_WAIT 多 = 没关连接 ✗
进程在但没响应线程栈jstack线程池满 / 死锁 ✗
磁盘满哪个目录df -h → du -sh *日志没轮转 ✗

★ 排查时优先"保留现场":重启前先抓 jstack、jstat、日志、连接状态 ✓(《Linux 服务部署与运维》 强调过)

6. 递进示例 ​

6.1 最小示例 ​

bash
ss -tlnp | grep :8080
ps -o pid,etime,cmd -p <PID>

6.2 业务示例:一次"启动失败" ​

text
① ./start.sh → "Port 8080 was already in use"
② ss -tlnp | grep :8080  → users:(("java",pid=12345,...))
③ ps -o pid,etime,cmd -p 12345 → java -jar /opt/order/app.jar(跑了 3 天)
   → 是"三天前忘了关的旧版本" ✓
④ kill 12345(等它优雅退出)
⑤ ./start.sh → 成功 ✓

6.3 反例:看到 PID 就 kill -9 ​

风险:如果那是别人的服务,你制造了一次事故 ✗✗

修:先看 COMMAND(5.3 的第 ③ 步)✓

7. 完整可运行命令 ​

环境说明:本机 Windows + Git Bash。ps、netstat、端口→PID 可实测 ✓; ss / lsof 是 Linux 工具(Windows 用 netstat -ano 代替);jstack 需要 JDK ✓

实测(一)进程:

bash
ps -ef | head -5        # 见 5.1:有 UID / PID / PPID / COMMAND

实测(二)端口与 PID:

bash
netstat -ano | grep -i "LISTENING" | head -6      # → 5432 的 PID 是 6704
netstat -ano | grep -ci "LISTENING"               # → 69

实测(三)用 PID 检查存活(《Linux 服务部署与运维》 脚本里的用法):

bash
cat /tmp/demo-service/app.pid      # → 1835
kill -0 1835 && echo "进程在 ✓"     # ★ kill -0 只检查存在性,不发信号

结论:

实测结论
5432 → PID 6704 ★端口能反查进程("端口被占用"的解法)✓
ps -ef 有 PPID 与 COMMAND能看到"谁启动的、跑了什么" ✓
kill -0脚本里判断存活的标准写法 ✓

8. Debug 观察点 ​

  1. 看 PID 与 PPID:找一个由 bash 启动的进程,确认它的 PPID 是那个 bash ✓;
  2. LISTENING vs ESTABLISHED:连一个本地服务再查,观察状态变化 ✓;
  3. ps -ef | grep java 会看到 grep 自己:用 grep [j]ava 对比 ✓;
  4. kill -0 练习:启动进程 → 检查 → 杀掉 → 再检查 ✓;
  5. Linux 上:ss -tlnp 与 netstat -tlnp 对比(ss 更快)✓。

9. 常见错误 ​

#错误说明
1不看 COMMAND 就 kill ✗✗可能杀掉别人的服务
2连不上就以为"服务挂了"可能是只监听 127.0.0.1 ✗(server.address=0.0.0.0)
3只看 CPU 不看 loadCPU 低 + load 高 = 在等(IO/锁)★
4重启前不抓现场原因消失,下次还会来 ✗
5kill -9 当常规手段破坏优雅停机(《Linux 服务部署与运维》)✗
6忽略 CLOSE_WAIT它是"连接泄漏"的信号 ✗
7把 TIME_WAIT 当问题通常正常;真正该警惕的是 CLOSE_WAIT ✓

10. 动手实验 ​

  1. 跑第 7 节的三条命令,读懂每一列 ✓;
  2. 找一个已知端口(如 5432)对应的 PID,再用 ps 查它是什么 ✓;
  3. 启动 deploy-demo.sh,用 ps 找到它,用 kill -0 检查,最后停止 ✓;
  4. 模拟"端口被占用":启动两次 deploy-demo.sh,观察第二次的行为(它应该报"已在运行")✓;
  5. 在 Linux / WSL 上:用 ss -tlnp 做一遍 ✓。

扩展任务:写 port.sh <端口号>:输出占用者的 PID/用户/启动时间/命令行;没人占用就输出"空闲";退出码:占用=0、空闲=1(可被其他脚本调用)★。

11. 练习题 ​

基础题

  1. 判断:LISTENING 表示"已经和客户端建立了连接"。(对 / 错)
  2. 填空:查端口占用用 ______;查进程命令行用 ______。
  3. 简答:CLOSE_WAIT 持续增长意味着什么?

代码阅读题

text
$ ss -tlnp | grep :8080
tcp  LISTEN  0  100  127.0.0.1:8080  0.0.0.0:*  users:(("java",pid=4321,fd=52))
  1. 这条输出说明了什么?
  2. "服务器本机 curl 能通,但别的机器连不上"最可能的原因是什么?怎么修?

编程题

  1. 写一个"服务健康巡检"脚本:检查进程、端口、健康检查接口、CPU、磁盘五项;每项输出 [OK]/[问题];有问题就 exit 1;用函数组织;set -uo pipefail(不用 -e)。回答:为什么要一次检查所有项?

综合任务

  1. 排查"服务假死":进程在、端口在监听,但所有请求超时,CPU 只有 5%。列出至少四种可能原因与对应命令;给出排查顺序;说明为什么"CPU 低却假死"更值得警惕。
参考答案(要点)

基础题

  1. 错。LISTENING = 在等别人来连;ESTABLISHED 才是已建立连接 ✓ (推论:进程在 ≠ 在监听 —— 可能启动了但初始化失败,所以"服务在不在"要看端口)★

  2. ss -tlnp | grep :8080;ps -o pid,etime,cmd -p <PID> ✓

  3. 应用没正确关闭 socket(连接泄漏) ✗ → 描述符耗尽 → 无法建新连接 → 假死 ✗✗

代码阅读题

  1. java 进程(PID 4321)只监听 127.0.0.1:8080 ⚠️ —— 只有服务器自己能连 ✗

  2. 最可能是只监听了 127.0.0.1(特征就是"本机通、外部不通")✓ 修:server.address=0.0.0.0,改完用 ss -tlnp 确认变成 0.0.0.0:8080 ✓ 如果监听地址没问题 → 再查防火墙/云安全组 ✓ 顺序:① 看监听地址 ② 本机 curl ③ 外部 curl ④ 防火墙 —— 由内到外 ✓

编程题

  1. 要点:不用 -e(要检查所有项);curl -f --max-time(避免卡死);ss 失败时 netstat 兜底;exit 1 接监控 ✓ 为什么检查所有项:很多时候"多个问题"其实是"一个根因的多个表现"(如磁盘满 → 日志写不了 → 健康检查失败)。只报第一个问题会让人去修症状 ✗

综合任务

  1. 可能原因与命令:
原因命令会看到
线程池耗尽 ★jstack大量线程 WAITING 在队列
连接池耗尽 ★jstack线程卡在 getConnection
死锁jstack"Found one Java-level deadlock" ★
等外部依赖jstack / 日志卡在 socketRead0;日志有 timeout
GC 停顿jstat -gcutilFGC/FGCT 大
等磁盘 IOtop(看 wa)CPU 低但 wa 高;进程状态 D

排查顺序:① jstack 抓 3 次(一次能排除死锁/线程池/连接池/等外部)→ ② jstat(排除 GC)→ ③ top(看 wa 与 load)→ ④ ss(连接堆积)→ ⑤ 日志与依赖方 ✓

为什么"CPU 低却假死"更值得警惕:

  • CPU 高 = 算不过来(做完就好,jstack 一眼看出在跑什么)✓
  • CPU 低 = 在等(等待的对象可能在别的系统,难定位;且不会自己结束,除非有超时)✗✗
  • 所以:"所有外部调用都要设超时"是铁律 ★★——否则下游不返回 → 线程一直等 → 线程池耗尽 → 假死 ✗

"假死"几乎都源于"等待没有上限"。防御方式就是:给每一个"等"都设一个上限。 ✓

12. 掌握标准 ​

  • [ ] 能读懂 ps -ef 的每一列(尤其 COMMAND)★;
  • [ ] 会用 ss -tlnp / netstat 由端口反查进程 ★★★;
  • [ ] 知道"端口被占用"的处理流程(且知道先看 COMMAND 再决定)★;
  • [ ] 能区分 LISTENING 与 ESTABLISHED,知道 CLOSE_WAIT 的含义 ★;
  • [ ] 会用 top / uptime,理解 load 与 CPU 的关系 ★;
  • [ ] 会用 jps / jstack / jstat ★★;
  • [ ] 面对"起不来 / 连不上 / 慢 / CPU 高"知道先查什么 ✓;
  • [ ] 知道排查时要"先保留现场"✓。

13. 扩展资源 ​

14. 下一步学习 ​

Linux 五节(《Linux 常用命令与部署》 / 《Linux 文件、用户与权限管理》 / 《Linux 服务部署与运维》 / 《Shell 脚本基础》 / 《进程与端口排查》)到此完成。接下来可以:

后续知识

暂无

进度只保存在本机浏览器,可随时清除

个人学习项目:AI 生成内容均经人工复核,第三方资源仅作索引