8080
80 被占走時,開發伺服器、Tomcat 或代理伺服器會改抓的那個連接埠;也是你需要它的時候,早就有人占著的那一個。
照你的系統挑一行貼上去執行。它會直接印出占著這個連接埠的行程,以及它綁在哪個位址上——通常看到這兩件事答案就出來了。
lsof -nP -iTCP:8080 -sTCP:LISTEN會印出占著這個連接埠的指令名稱、PID、使用者,以及它綁在哪個位址上。`127.0.0.1:8080` 代表只綁回送位址,這正是同一個 Wi-Fi 下的手機連不到的原因;`*:8080` 則是每一張介面。沒有輸出就代表這個連接埠真的是空的。監聽者屬於別的使用者時記得加 `sudo`。如果指令欄出現 `Docker` 或 `com.docker.backend`,那是容器發布出來的連接埠,要停的是容器,不是去砍那個行程。
sudo ss -tlnp 'sport = :8080'`-t` 挑 TCP,`-l` 只看監聽中的,`-n` 讓連接埠維持數字,`-p` 用 `users:(("java",pid=8123,fd=50))` 的形式補上所屬行程。本機位址那一欄要看仔細:`[::]:8080` 是 IPv6 萬用位址,通常連 IPv4 也一起收;但如果旁邊還單獨列了一行 `0.0.0.0:8080`,代表 IPv4 那一側被第二個行程拿走了。不加 `sudo` 的話,不屬於你的那些行程欄會是空的。
netstat -ano | findstr :8080最後一欄是持有這個 socket 的 PID,用 `tasklist /FI "PID eq 8123"` 換成名字。`findstr` 比的是子字串,所以遠端位址裡的 `:8080` 也會被撈進來——動手之前先確認本機位址那一欄。如果什麼都沒列出來、綁定卻還是失敗,問題就在下面那個保留範圍。
netsh interface ipv4 show excludedportrange protocol=tcp當 8080 上沒有任何監聽、綁定卻還是失敗時,跑這一行。Hyper-V、WSL2、Docker Desktop 和 Windows 的 NAT 服務會在開機時預留幾段動態連接埠,只要其中一段剛好蓋到 8080,每一次綁定都會失敗,而且找不到任何行程可以怪。如果 8080 落在列出來的範圍裡,要嘛重啟那個占走它的主機服務,要嘛把自己的伺服器換到所有範圍以外的號碼。
`nmap -Pn -p 8080 example.com` 回答的是「從這台機器外面看,那裡有沒有東西連得到」。`open` 代表 TCP 交握完成;`closed` 代表主機回了 reset,也就是機器活著但沒人在聽;`filtered` 代表探測封包消失了,被防火牆丟掉。加 `--reason` 可以看出實際是哪一種,加 `-sV` 會讓 nmap 取回應並回報伺服器 banner——你常常就是這樣才發現 8080 上是一個早就忘掉的 Tomcat。只掃你自己負責的主機。
| 你看到的訊息 | 代表什麼 |
|---|---|
Error: listen EADDRINUSE: address already in use :::8080 | 已經有別的行程占著這個連接埠了。`:::8080` 這種寫法是 IPv6 萬用位址,在多數系統上連 IPv4 也一起蓋掉,所以綁在那裡的服務會把兩邊都擋住。用你系統對應的那行指令找出持有者;十次有九次是同一個伺服器上一輪的執行,只是被丟到背景而沒有真的停掉。 |
Only one usage of each socket address (protocol/network address/port) is normally permitted | 同一件事的 Windows 說法,錯誤碼 10048。如果 `netstat` 根本沒列出任何監聽,那就不是被占用而是被保留:先用上面那行 `netsh` 查保留範圍,不要去追一個不存在的行程。 |
The server says it started, but another device on the same network gets connection refused | 它綁到了 `127.0.0.1` 而不是 `0.0.0.0`。現在很多框架是刻意改成預設綁回送位址的,所以這是一個設定參數而不是 bug——`--host 0.0.0.0`、`HOST=0.0.0.0` 或對應的寫法。用上面的指令確認一下:位址那一欄會告訴你它選了哪一個。 |
The port frees itself about a minute after the server exits | 連線還開著就被關掉的 socket 會停在 `TIME_WAIT` 最多兩分鐘,在那之前新的綁定會被拒絕,除非程式有設 `SO_REUSEADDR`。等它過去可以,換一個連接埠啟動也可以。沒有東西需要被砍。 |
8080 answers, but with something you did not start | 通常是某個容器還在發布這個連接埠——`docker ps` 會把 `0.0.0.0:8080->8080/tcp` 那一行秀出來。也可能是開機就啟動的服務,例如 Tomcat 或印表機的管理介面。對自己的機器跑 `nmap -sV`,它會讀 banner 並告訴你那是什麼。 |
IANA 把 8080 登記為 `http-alt`(HTTP Alternate),TCP 和 UDP 都有,所以號碼本身是有指派的,只是上面實際跑什麼比較算慣例。它會變成這麼多軟體的預設值,理由其實很平凡:Unix 系統上 1024 以下是特權連接埠,要綁 80 得有 root 或被授予的能力,而 8080 兩者都不需要。於是它就成了所有開發者手動啟動的東西的落腳處——Tomcat 的預設 connector、Jenkins、Spring Boot、Vite 或 webpack 的代理、Docker 發布出來的 Web 容器連接埠,以及在 443 終結 TLS 的反向代理背後那個來源站。這個號碼代表的就只是純文字 HTTP,沒有別的:它不加密、對瀏覽器沒有任何特殊意義,`http://host:8080/` 只是一個送到不常見號碼上的普通 HTTP 請求。也因為用它的軟體太多,被占用的 8080 十之八九是你自己的另一個行程,而不是什麼神祕的東西——下面的指令一行就能把它點名出來。
把服務從 80 搬到 8080 對安全完全沒有幫助。掃全網的機器掃 8080 跟掃 80 一樣勤,被發現所需的時間是一樣的。8080 在實務上比較危險,是因為住在上面的東西通常是本來就不該對外的:Tomcat 的 manager 應用、還停在初始設定精靈的 Jenkins、Spring Boot 的 actuator 端點、容器的除錯介面。開發伺服器請綁 `127.0.0.1`,讓它出不了這台機器;真的要對外的東西,走 443 上終結 TLS 的反向代理,而不是在防火牆上把 8080 打開。如果非開不可,就限制來源位址並在前面擺一道認證;而且要當它是純文字在傳,因為它本來就是。
這些全都在你的瀏覽器裡跑,不會上傳任何東西。
查 8080 的時候,通常也會順手看一下這幾個。
幾乎都是權限問題。lsof 和 ss 會列出 socket,但別人的行程它不會顯示所有者,所以由系統帳號、容器執行環境或 launchd 啟動的服務,在你補上 sudo 之前就只是一個沒有主人的監聽項。Windows 則是反過來:netstat 什麼都沒有,綁定卻還是失敗,那代表這個號碼落在 Hyper-V、WSL2 或 Docker Desktop 開機時預留的範圍裡。
先看清楚它是什麼。沒收乾淨的開發伺服器砍掉沒事;正在寫入的資料庫不行,其他東西依賴的系統服務也不行。如果持有者是容器,請停容器,不要砍主機看到的那個行程——砍了執行環境只會把它拉起來。遇到真的不能動的,把自己的服務換一個連接埠反而更快。
因為它綁在 127.0.0.1 而不是 0.0.0.0。每一頁的指令之所以會把綁定位址跟行程名一起印出來,就是為了這件事:綁在回送位址上的服務,不管防火牆怎麼設,都只有這台機器自己連得到。現在不少框架是刻意這樣預設的,所以通常是一個參數的問題,不是 bug。如果已經是 0.0.0.0 還是不通,下一個要懷疑的就是主機防火牆或雲端的安全群組。
幾乎沒有幫助。掃全網的機器持續在掃整段範圍,換號碼買到的是幾個小時,不是安全,代價卻是每個同事都得記住它。它確實能讓針對預設埠的無差別掃描少污染一點日誌,這算是實際但有限的好處。真正會改變結果的是認證、限制來源位址的防火牆,以及一開始就不要讓它對外。
連接埠 8080 還是卡住嗎?看完整的連接埠對照表,或是回到上面,從你實際看到的那行錯誤往回追。