故障排查
排查总原则
按分层排查:IPv6 → 连接层 → VM 层 → PVE 层。先确认基础连通性,再查上层逻辑。不要上来就改代码或手动改配置。
终端不在线
现象:终端上电后,教师端终端列表里看不到这台终端,或状态一直显示"离线"。
排查步骤(按顺序)
1. 确认终端本机网络
# 在终端上执行
ip addr show
# 确认:
# 1) 网卡接口存在(如 enp1s0)
# 2) 有 IPv4 地址
# 3) 有 IPv6 fe80:: 链路本地地址
ping 教师端IP
# 能 ping 通说明物理连接正常
如果没有 fe80 地址
终端和教师端之间的通信走 IPv6 链路本地地址。没有 fe80 地址意味着 discover 完全无法启动。检查网卡是否 UP、驱动是否正常。
2. 确认教师端后端运行中
# 在教师端电脑上
# 查看 communication_module.exe 是否在运行
# 查看日志是否有 listening 和 announce
# 测试教师端端口是否监听
# 默认端口 8790
3. 测试 IPv6 多播
# 在终端上执行
ping6 -c 3 -I enp1s0 ff02::1
# 应该能看到多个设备回包,包括教师端
# 检查邻居表
ip -6 neigh show
# 教师端的 fe80 地址应出现在列表中,且状态不是 FAILED
4. 检查终端程序日志
# 在终端上查看
journalctl -u terminal-service -n 50
# 或查看终端程序自己的日志文件
# 关键日志关键词:
# "discover_teacher started" → 发现线程已启动
# "teacher found" → 发现成功
# "connected" → 注册成功
# 如果没有 "discover_teacher started" → 检查开机自启配置
禁止的操作
以下操作属于违规,不会解决问题反而制造更多混乱:
- 手动写 teacher_ip6 到 .terminal_config
- 手动 TCP connect 触发邻居发现
- 手动修改 DB 记录
- 手动分配 terminal_id
桌面接入失败
现象:教师端点上课后,VM 已启动(PVE 里能看到 running),但终端屏幕没有显示桌面,一直黑屏或卡在等待。
排查步骤
| 步骤 | 检查内容 | 预期结果 |
|---|---|---|
| 1 | PVE 里 VM 状态 | running,QEMU 进程存在 |
| 2 | VM MAC 绑定 | VM 的 net0 MAC 与终端 MAC 一致 |
| 3 | SPICE ss 状态 | PVE 报告 SPICE 连接已建立 |
| 4 | 终端到 PVE 网络连通性 | 终端能 ping 通 PVE IP |
| 5 | VM 内部 Guest 程序 | guest-service 在运行,心跳正常 |
常见原因
- VM MAC 不匹配:克隆 VM 时 MAC 没有正确继承。需要确认 PVE VM 配置里的 MAC 与终端 MAC 一致
- SPICE 端口不通:PVE 防火墙规则阻止了 SPICE 端口。检查 PVE Firewall 配置
- VM 内部 Guest 程序未启动:模板里 guest-service 没有设为开机自启
- 存储 IOPS 不足:60 台同时启动时 SSD 跟不上,VM 启动极慢。检查 PVE 存储性能
SPICE 桌面断开恢复
现象:上课过程中,学生终端桌面突然断开,屏幕回退到终端主界面。
两种断开类型
| 类型 | 触发原因 | 终端行为 |
|---|---|---|
| 自然断开 | 网络波动、PVE 负载尖峰、remote-viewer 崩溃 | 自动尝试重新连接(两次机会),失败后显示恢复按钮 |
| 热键退出 | 学生按 Ctrl+Shift+F12(VM 卡死/蓝屏/无响应) | 不自动重连,直接显示双按钮:重新连接 / 重新上课 |
怎么区分?
热键退出会在终端上留下一个临时标记文件。终端检测到这个标记,就知道是用户主动操作的,走热键恢复流程。没有标记就是自然断开,走自动恢复流程。
排查步骤
1. 确认断开类型
# 在终端上查看 SPICE 相关日志
# 搜 "spice_disconnected" 关键词
# reason=normal → 可能是网络波动
# reason=error → 可能是 PVE 侧问题
# 出现 hotkey_triggered → 学生按了 Ctrl+Shift+F12
2. 自然断开 → 检查自动恢复
# 查看自动恢复状态
# 搜 "auto_recovery_status":
# first_attempt → 首次重连尝试中
# second_attempt → 第二次重连尝试中(此时显示"重新上课"按钮)
# recovering → 正在恢复
# reclone_start → 教师端已开始重克隆 VM
# 如果 first_attempt 之后就停了:
# 网络不通?→ 从终端 ping PVE IP
# PVE API 不可达?→ 检查 PVE 服务状态
3. 热键退出 → 选哪个按钮
| 按钮 | 选它的条件 | 效果 |
|---|---|---|
| 重新连接 | 网络波动、短暂断线、remote-viewer 崩溃 | 本地重启 remote-viewer,秒级恢复,VM 不受影响 |
| 重新上课 | VM 蓝屏、卡死、无响应、反复断线 | 发请求给教师端 → 教师端停止并删除当前 VM → 重新克隆新 VM → 推送新连接指令 → 终端连上新 VM |
"重新上课"会丢失数据
选了"重新上课",当前 VM 会被销毁并重建。学生在 VM 上未保存的文件、临时操作会全部丢失。确认 VM 确实不可恢复时再用这个选项。
常见原因
- 自然断开频繁出现:检查 PVE 负载(CPU/内存/磁盘 IO),60 台同时运行时 SPICE 总带宽需求很低(< 100 Mbps),通常不是网络问题
- 热键被误触发:Ctrl+Shift+F12 是系统级快捷键,老师可以在教师端确认是否有学生频繁触发
- VM 蓝屏:属于 Guest 程序不可恢复的故障,只能用"重新上课"重建 VM
- SPICE 端口冲突:检查 PVE 上 VM 的 SPICE 端口是否与 VMID 正确对应(公式:61000 + VMID)
USB 透传异常
现象:终端插上 U 盘、键盘、鼠标后,VM 内部无法识别设备。
排查步骤
- 确认 PVE VM 配置里有 USB 透传设备:
# 在 PVE shell 中查看 VM 配置 qm config VMID | grep usb # 应该看到 usb0/usb1 等配置 - 确认 Windows 模板里安装了 SPICE Guest Tools(含 usbredir 支持)
- 确认终端 SPICE 客户端版本支持 USB 重定向
- 在 VM 内部设备管理器里查看 USB 设备是否出现
常见原因
- 模板缺少 SPICE Guest Tools → 在模板中重新安装
- PVE VM 配置缺少 USB 控制器 → 在 PVE 界面添加 USB 设备
- USB 设备需要特定驱动 → 在 VM 内部安装对应驱动
VM 克隆后网络异常
现象:VM 启动后,内部网络不通(无 IP 或 IP 冲突),导致桌面功能异常。
Debian 13 / netplan 冲突(最常见)
如果 VM 内部是 Debian 系统,且使用了 netplan + systemd-networkd,克隆后可能出现 MAC 地址绑定问题:
# 问题原因:
# /etc/netplan/50-cloud-init.yaml 中 match 了硬编码 MAC
# 克隆后 MAC 变了,配置不生效
# systemd-networkd 标记接口为 unmanaged
# 检查:
networkctl
# 如果看到 "degraded" 或 "unmanaged",说明配置没生效
# 修复:
# 方案 1(推荐):修改 netplan 配置,去掉 MAC 匹配
# match: { name: "en*" } 替代 match: { macaddress: "..." }
# 方案 2:清除 cloud-init 缓存
sudo rm -rf /var/lib/cloud/instances/*
sudo cloud-init clean
sudo reboot
IP 冲突检测
如果多台 VM 分到了相同的 IP(克隆时 ipconfig0 相同),会导致 ARP 冲突,接口 DOWN:
# 在 PVE 上检查
dmesg | grep "entered disabled\|entered forwarding"
# 如果看到 forwarding,说明 PVE 层没问题,是 VM 内部问题
# 修复:为每个 VM 分配唯一 IP
qm set VMID -ipconfig0 ip=唯一IP/24,gw=网关
IPv6 discover 失败
现象:终端无法通过 IPv6 链路本地地址发现教师端。
Win10 教师端特殊行为
Win10 不响应 ff02::1 ping
Win10 默认不响应 IPv6 多播 ping。不能把"终端 ping6 ff02::1 能否收到教师端回包"作为 discover 成功的判断标准。
排查步骤
- 在终端上检查教师端的 fe80 地址是否在邻居表:
ip -6 neigh show | grep 教师端MAC # 教师端 fe80 地址应出现,且状态不是 FAILED - 测试到教师端端口的 TCP 连接:
# 链路本地地址必须带 zone-id python3 -c " import socket s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) s.settimeout(5) scope = socket.if_nametoindex('enp1s0') s.connect(('fe80::教师端地址', 8790, 0, scope)) print('OK') s.close() " - 检查教师端是否在监听 IPv6:
# 在教师端上 ss -tlnp | grep 8790 # 应看到 [::]:8790,表示监听所有 IPv6
常见原因
- 教师端只绑定了 IPv4,没有监听 IPv6(检查
[::]:8790) - IPv6 链路本地地址 zone-id 被剥离(getaddrinfo 会丢 zone-id,需要手动传 scope_id)
- 教师端防火墙阻止了 UDP 多播或 TCP 8790
- 终端网卡没有 fe80 地址(驱动或接口 DOWN)
教师端连不上终端
现象:教师端能正常启动,但终端列表为空,或部分终端间歇性掉线。
排查顺序
- 先确认教师端自己正常:communication_module 日志有无报错
- 再确认网络:从教师端 ping 终端 IP
- 检查心跳日志:教师端日志里哪些终端的心跳超时了
- 检查 VM 双 MAC 问题:VM 克隆时继承了终端 MAC,导致同一 MAC 双路心跳(终端本机 + VM 内部),按 MAC 反查归一到同 tid,DB 里 IP 被交替覆盖
IP 来回跳的根因
VM 内 Guest 程序也会发心跳,如果用同一 MAC 发,教师端会把终端和 VM 的心跳都归一到同一 tid。终端本机 IP 和 VM 内部 IP 就会被交替写入 DB,导致左列 IP 来回跳。VM 内部 IP 仅供 PVE 校验,不应该覆盖终端 IP。
常见错误码与现象索引
| 现象 | 可能原因 | 参考章节 |
|---|---|---|
| 终端上电后教师端看不到 | discover 未启动 / 网络 / IPv6 | 终端不在线 |
| 终端能看到但状态不对 | 心跳超时 / TCP 探测失败 | 教师端连不上 |
| VM 启动了但桌面黑屏 | SPICE 未连接 / MAC 不匹配 | 桌面接入 |
| U 盘插了没反应 | USB 透传 / SPICE Guest Tools | USB 异常 |
| VM 内部网络不通 | netplan MAC 匹配 / IP 冲突 | VM 网络 |
| IP 在列表里来回跳 | VM 双 MAC 心跳归一 | 双 MAC 问题 |
| 终端列表 IP 一会有一会没 | 心跳分流时 IP/MAC/status 一起拆了吗 | 五维度独立原则 |
| 升级后终端不工作 | os.rename 防 Text file busy | 终端升级 |
| PVE 连接被拒 | 密码错误或 PVE 服务未启动 | 教师端配置 |
| 桌面突然断开,屏幕回终端界面 | SPICE 断线(网络/热键/VM蓝屏) | SPICE 恢复 |
| 按 Ctrl+Shift+F12 后桌面没反应 | Openbox 快捷键未配置或 X 会话异常 | 热键恢复 |