DeepTutor 的 backend 跑起來了,但前端所有 API 請求都沒有響應。打開 http://localhost:8001 看到的不是 FastAPI 的文檔頁,而是一個完全陌生的 UI。
1. 排查過程
1.1. 確認哪些端口被佔用
1Get-NetTCPConnection -State Listen |
2 Select-Object LocalPort, OwningProcess |
3 Sort-Object LocalPort -Unique |
4 ForEach-Object {
5 $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
6 [PSCustomObject]@{
7 Port = $_.LocalPort
8 PID = $_.OwningProcess
9 Process = if ($proc) { $proc.ProcessName } else { "Unknown" }
10 }
11 } | Sort-Object Port | Format-Table -AutoSize
結果顯示 8001 上有兩個 python 進程同時 LISTENING,一個綁定在 127.0.0.1:8001,另一個綁定在 0.0.0.0:8001。
1.2. 查出是誰在跑
用 WMI 查出完整命令列:
1Get-WmiObject Win32_Process -Filter "ProcessId=6396" |
2 Select-Object ProcessId, Name, ExecutablePath, CommandLine
結果一目了然:
- PID 6396:
ComfyUI/main.py --port 8001(ComfyUI 後端) - PID 39944:
python -m deeptutor.api.run_server(DeepTutor 後端)
1.3. 為什麼請求全都給了 ComfyUI
Windows TCP 路由有一個關鍵行為:當多個進程同時綁定同一端口的不同地址時,更具體的綁定優先。
1127.0.0.1:8001 ← ComfyUI(更具體) ✓ 獲得所有 localhost 連線
20.0.0.0:8001 ← DeepTutor ✗ 永遠收不到 localhost 請求
DeepTutor 雖然在跑,但因為 ComfyUI 先綁定了 127.0.0.1:8001,所有來自 localhost 的請求都被路由給了 ComfyUI。
1.4. 爲什麽 ComfyUI 被關了視窗卻還在跑
1Get-WmiObject Win32_Process | Where-Object {
2 $_.CommandLine -like "*ComfyUI*"
3} | Select-Object ProcessId, ParentProcessId, Name, CommandLine
進程樹揭示了兩個不同的根本原因:
原因一:Chrome PWA 背景行為
1chrome.exe (主瀏覽器)
2 └─ chrome.exe (renderer)
3 └─ python.exe ← ComfyUI main.py --port 8001
4 └─ python.exe (uv)
ComfyUI 曾被安裝為 Chrome PWA。Chrome 有一個預設開啟的設定:「Google Chrome 關閉後,繼續在背景執行應用程式」。關掉 PWA 視窗只是關掉視窗,Chrome renderer 進程及其所有子進程繼續存活。
原因二:Electron 孤兒進程
另外兩個 ComfyUI 實例(port 8000、8002)的父進程已不存在,成了孤兒進程。
這是 ComfyUI Desktop(Electron app)的設計缺陷:關閉 Electron 視窗時沒有正確終止子進程,Python backend 就這樣繼續在背景跑。
2. 解決方案
2.1. 立即清理
1# 一次性 kill 所有 ComfyUI 殘留進程
2Get-WmiObject Win32_Process | Where-Object {
3 $_.CommandLine -like "*ComfyUI/main.py*"
4} | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
2.2. 永久預防
- 針對 Chrome PWA 問題:進入 chrome://settings/system,關閉「Google Chrome 關閉後,繼續在背景執行應用程式和擴充功能」。
- 針對 Electron 孤兒進程問題:不要直接按視窗的 X 關閉 ComfyUI Desktop,要從選單 File → Quit 或系統匣右鍵 → 退出,讓 Electron 完整走退出流程並清理子進程。
3. 經驗教訓
- 端口被佔用不等於服務沒啟動。 你的服務可能已經在跑,只是被更具體的綁定搶走了所有連線。
- 關閉視窗 ≠ 關閉程式。 特別是 Electron app 和 Chrome PWA,都可能在背景保留進程。
- 排查端口衝突要看完整的命令列,netstat -ano 加 Get-WmiObject Win32_Process 查看最完整的圖景。